Come verificare un metodo viene chiamato una sola volta, con argomenti specifici (usando RhinoMocks)

1

Sto appena iniziando a usare RhinoMocks. Ora mi chiedo quali casi di test dovrei scrivere. Voglio affermare che un metodo viene chiamato una sola volta, con argomenti specifici.

Iniziamo con le mie interfacce.

public class BarQueryParameters
{
    public int Id { get; set; }
    public List<string> Categories { get; set; }
}

public interface IBar
{
    void CalFoo(BarQueryParameters parameters);
}

public class FooQueryParameters
{
    public string Id { get; set; }
    public List<string> Types { get; set; }
}

public interface IFoo
{
    IEnumerable<string> CallMe(FooQueryParameters parameters);
}

Poi abbiamo la classe Bar che implementa IBar e chiama il metodo IFoo di CallMe :

public class Bar : IBar
{
    private readonly IFoo _foo;

    public Bar(IFoo foo)
    {
        _foo = foo;
    }

    public void CalFoo(BarQueryParameters parameters)
    {
        List<string> result = _foo.CallMe(new FooQueryParameters
        {
            Id = parameters.Id.ToString(),
            Types = parameters.Categories.ToList()
        }).ToList();
        Console.WriteLine(result.Count);
    }
}

Voglio verificare che se CallFoo viene chiamato con Id = 1 , Categories = new List<string> {"One", "Two"} , ciò comporta una chiamata a IFoo.CallMe . Voglio assicurarmi che i FooQueryParameters siano ciò che mi aspetto.

All'inizio ho scritto:

    [TestMethod]
    public void TestFooBarConversion2()
    {
        IFoo mockedFoo = MockRepository.GenerateMock<IFoo>();
        mockedFoo.Expect(foo => foo.CallMe(Arg<FooQueryParameters>
            .Matches(p => p.Id.Equals("1") && p.Types.SequenceEqual(new List<string> {"One", "Two"}))))
            .Repeat.Once();

        IBar bar = new Bar(mockedFoo);
        bar.CalFoo(new BarQueryParameters {Id = 1, Categories = new List<string> {"One", "Two"}});

        mockedFoo.VerifyAllExpectations();
    }

Questo non funzionerà in quanto Bar si aspetta un risultato dalla sua chiamata a Foo.CallMe (prova a ToList() del risultato). Attualmente il test risulterà in NullReferenceException . Quindi, dovrei anche assicurarmi che il mio metodo di simulazione restituisca qualcosa come new List<string>() .

Ancora non ci sono però. Che cosa accadrebbe se Bar contiene un errore di programmazione e chiama CallMe con argomenti non corretti? In tal caso, il test dell'unità fallirà, ma non su VerifyAllExpectations . Verrà nuovamente eseguito in NullReferenceException .

Quindi ora direi che il mio% deriso% co_de dovrebbe sempre restituire un CallMe . Ma vorrei comunque assicurarmi che venga chiamato una volta con gli argomenti previsti. Voglio anche assicurarmi che sia not chiamato con qualsiasi altro argomento.

Quindi vorrei:

    [TestMethod]
    public void TestFooBarConversion()
    {
        IFoo mockedFoo = MockRepository.GenerateMock<IFoo>();
        mockedFoo.Expect(foo => foo.CallMe(Arg<FooQueryParameters>
            .Matches(p => p.Id.Equals("1") && p.Types.SequenceEqual(new List<string> {"One", "Two"}))))
            .Repeat.Once()
            .Return(new List<string>());
        mockedFoo.Expect(foo => foo.CallMe(Arg<FooQueryParameters>
            .Matches(p => !p.Id.Equals("1") || !p.Types.SequenceEqual(new List<string> {"One", "Two"}))))
            .Repeat.Never()
            .Return(new List<string>());

        IBar bar = new Bar(mockedFoo);
        bar.CalFoo(new BarQueryParameters {Id = 1, Categories = new List<string> {"One", "Two"}});

        mockedFoo.VerifyAllExpectations();
    }

Questo non mi sembra giusto.

  1. C'è un modo più semplice per farlo?
  2. Non mi interessa se il metodo viene anche chiamato con altri argomenti?
  3. Non mi interessa se il test fallisce su un new List<string>() ?
posta comecme 29.05.2015 - 08:35
fonte

0 risposte

Leggi altre domande sui tag