J'essaie d'apprendre la syntaxe de Rhino Mocks AAA, et j'ai du mal à affirmer qu'une certaine méthode (avec n'importe quelle valeur d'argument) a été appelée. J'utilise Machine.Specifications comme cadre de test.Comment AssertWasCalled une méthode générique avec trois types différents en utilisant RhinoMocks?
Cette méthode particulière est générique et je veux m'assurer qu'elle a été appelée trois fois avec trois types différents.
repo.Save<T1>(anything), repo.Save<T2>(anything), and repo.Save<T3>(anything)
J'ai écrasé la fonction pour chaque type. Mais je reçois un résultat intéressant. (ci-dessous)
[Subject("Test")]
public class When_something_happens_with_constraint
{
static IRepository repo;
static TestController controller;
static ActionResult result;
Establish context =() =>
{
repo = MockRepository.GenerateMock<IRepository>();
controller = new TestController(repo);
repo.Stub(o => o.Save<Something>(Arg<Something>.Is.Anything));
repo.Stub(o => o.Save<SomethingElse>(Arg<SomethingElse>.Is.Anything));
repo.Stub(o => o.Save<AnotherOne>(Arg<AnotherOne>.Is.Anything));
};
//post data to a controller
Because of =() => { result = controller.SaveAction(new SomethingModel() { Name = "test", Description = "test" }); };
//controller constructs its own something using the data posted, then saves it. I want to make sure three calls were made.
It Should_save_something =() => repo.AssertWasCalled(o => o.Save<Somethign>(Arg<Something>.Is.Anything));
It Should_save_something_else =() => repo.AssertWasCalled(o => o.Save<SomethingElse>(Arg<SomethingElse>.Is.Anything));
It Should_save_another_one =() => repo.AssertWasCalled(o => o.Save<AnotherOne>(Arg<AnotherOne>.Is.Anything));
}
Le résultat est deux exceptions et une passe.
Le premier appel lance:
System.InvalidOperationException: Aucune attentes ont été installés à vérifier, assurez-vous que l'appel de méthode dans l'action est un virtuel (C#)/Overridable (VB.Net) appel de méthode
La seconde lance:
System.InvalidOperationException: Utiliser Arg seulement dans un appel de méthode maquette en cours d'enregistrement. 1 arguments attendus, 2 ont été définis.
Le troisième passe ... pour une raison étrange.
J'ai également essayé d'utiliser GenerateMock() avec Expect dans ma configuration et d'utiliser GenerateStub() avec Stub. Les deux ont fini avec le même résultat. Je dois faire quelque chose de mal.
J'utilise: MachineSpec 0.3.0.0 et 3.6.0.0 RhinoMocks
Toutes les idées?
----- ---------- FIXE
Voici la complète (version de travail) avec l'aide de Lee. J'utilise une couche supplémentaire (non-linq). Mon problème réel était que l'un de mes tests réutilisait la mauvaise variable lambda dans le code réel hors ligne. Il Should_do_something =() => repo.AssertWasCalled (o =>repo .Save (données)); // mauvais lambda
Voici donc un exemple de test correct pour référence.
using System;
using System.Linq;
using System.Collections.Generic;
using Machine.Specifications;
using Rhino.Mocks;
namespace OnlineTesting.Specifications
{
public interface Repository
{
void Save<T>(T data);
IQueryable<T> All<T>();
}
public interface Service
{
void SaveItem(Item data);
void SaveAnotherItem(AnotherItem data);
void SaveOtherItem(OtherItem data);
List<Item> GetItems();
List<AnotherItem> GetAnotherItems();
List<OtherItem> GetOtherItems();
}
public class ConcreteService : Service
{
Repository repo;
public ConcreteService(Repository repo)
{
this.repo = repo;
}
public void SaveItem(Item data)
{
repo.Save(data);
}
public void SaveAnotherItem(AnotherItem data)
{
repo.Save(data);
}
public void SaveOtherItem(OtherItem data)
{
repo.Save(data);
}
public List<Item> GetItems()
{
return repo.All<Item>().ToList();
}
public List<AnotherItem> GetAnotherItems()
{
return repo.All<AnotherItem>().ToList();
}
public List<OtherItem> GetOtherItems()
{
return repo.All<OtherItem>().ToList();
}
}
public class Item
{
public int Id { get; set; }
}
public class OtherItem
{
}
public class AnotherItem
{
}
public class When_something_else_happens
{
Establish context =() =>
{
_repository = MockRepository.GenerateMock<Repository>();
_service = new ConcreteService(_repository);
_controller = new TestController(_service);
_repository.Stub(o => o.Save<Item>(Arg<Item>.Is.Anything)).WhenCalled(
new Action<MethodInvocation>((o) =>
{
var data = o.Arguments.FirstOrDefault() as Item;
if (data != null && data.Id == 0)
data.Id++;
}));
};
Because of =() => _controller.DoSomethingElse();
It should_save_the_first_thing =() =>
_repository.AssertWasCalled(repo => repo.Save(Arg<Item>.Is.Anything));
It should_save_the_other_thing =() =>
_repository.AssertWasCalled(repo => repo.Save(Arg<OtherItem>.Is.Anything));
It should_save_the_last_thing =() =>
_repository.AssertWasCalled(repo => repo.Save(Arg<AnotherItem>.Is.Anything));
static Repository _repository;
static TestController _controller;
static Service _service;
}
public class TestController
{
readonly Service _service;
public TestController(Service service)
{
_service = service;
}
public void DoSomethingElse()
{
_service.SaveItem(new Item());
_service.SaveOtherItem(new OtherItem());
_service.SaveAnotherItem(new AnotherItem());
}
}
}
Aussi ... Je ne peux pas configurer les arguments avant l'appel car l'action du contrôleur construit un nouvel objet et le passe au référentiel. Donc j'utilise Arg .Il n'y a rien. Je veux juste m'assurer que repo.save a été appelé pour un type spécifique. –
Nathan