The short takeaway now that the solution has been found:
AutoFixture returns frozen the mock just fine; my sut that was also generated by AutoFixture just had a public property with a local default that was important for the test and that AutoFixture set to a new value. There is much to learn beyond that from Mark's answer.
Original question:
I started trying out AutoFixture yesterday for my xUnit.net tests that have Moq all over them. I was hoping to replace some of the Moq stuff or make it easier to read, and I'm especially interested in using AutoFixture in the SUT Factory capacity.
I armed myself with a few of Mark Seemann's blog posts on AutoMocking and tried to work from there, but I didn't get very far.
This is what my test looked like without AutoFixture:
[Fact]
public void GetXml_ReturnsCorrectXElement()
{
// Arrange
string xmlString = #"
<mappings>
<mapping source='gcnm_loan_amount_min' target='gcnm_loan_amount_min_usd' />
<mapping source='gcnm_loan_amount_max' target='gcnm_loan_amount_max_usd' />
</mappings>";
string settingKey = "gcCreditApplicationUsdFieldMappings";
Mock<ISettings> settingsMock = new Mock<ISettings>();
settingsMock.Setup(s => s.Get(settingKey)).Returns(xmlString);
ISettings settings = settingsMock.Object;
ITracingService tracing = new Mock<ITracingService>().Object;
XElement expectedXml = XElement.Parse(xmlString);
IMappingXml sut = new SettingMappingXml(settings, tracing);
// Act
XElement actualXml = sut.GetXml();
// Assert
Assert.True(XNode.DeepEquals(expectedXml, actualXml));
}
The story here is simple enough - make sure that SettingMappingXml queries the ISettings dependency with the correct key (which is hard coded/property injected) and returns the result as an XElement. The ITracingService is relevant only if there's an error.
What I was trying to do is get rid of the need to explicitly create the ITracingService object and then manually inject the dependencies (not because this test is too complex, but because it is simple enough to try things out and understand them).
Enter AutoFixture - first attempt:
[Fact]
public void GetXml_ReturnsCorrectXElement()
{
// Arrange
IFixture fixture = new Fixture();
fixture.Customize(new AutoMoqCustomization());
string xmlString = #"
<mappings>
<mapping source='gcnm_loan_amount_min' target='gcnm_loan_amount_min_usd' />
<mapping source='gcnm_loan_amount_max' target='gcnm_loan_amount_max_usd' />
</mappings>";
string settingKey = "gcCreditApplicationUsdFieldMappings";
Mock<ISettings> settingsMock = new Mock<ISettings>();
settingsMock.Setup(s => s.Get(settingKey)).Returns(xmlString);
ISettings settings = settingsMock.Object;
fixture.Inject(settings);
XElement expectedXml = XElement.Parse(xmlString);
IMappingXml sut = fixture.CreateAnonymous<SettingMappingXml>();
// Act
XElement actualXml = sut.GetXml();
// Assert
Assert.True(XNode.DeepEquals(expectedXml, actualXml));
}
I would expect CreateAnonymous<SettingMappingXml>(), upon detection of the ISettings constructor parameter, to notice that a concrete instance has been registered for that interface and inject that - however, it doesn't do that but instead creates a new anonymous implementation.
This is especially confusing as fixture.CreateAnonymous<ISettings>() does indeed return my instance -
IMappingXml sut = new SettingMappingXml(fixture.CreateAnonymous<ISettings>(), fixture.CreateAnonymous<ITracingService>());
makes the test perfectly green, and this line is exactly what I had expected AutoFixture to do internally when instantiating SettingMappingXml.
Then there's the concept of freezing a component, so I went ahead just freezing the mock in the fixture instead of getting the mocked object:
fixture.Freeze<Mock<ISettings>>(f => f.Do(m => m.Setup(s => s.Get(settingKey)).Returns(xmlString)));
Sure enough this works perfectly fine - as long as I call the SettingMappingXml constructor explicitly and don't rely on CreateAnonymous().
Simply put, I don't understand why it works the way it apparently does, as it goes against any logic I can conjure up.
Normally I would suspect a bug in the library, but this is something so basic that I'm sure others would have run into this and it would long have been found and fixed. What's more, knowing Mark's assiduous approach to testing and DI, this can't be unintentional.
That in turn means I must be missing something rather elementary. How can I have my SUT created by AutoFixture with a preconfigured mocked object as a dependency? The only thing I'm sure about right now is that I need the AutoMoqCustomization so I don't have to configure anything for the ITracingService.
AutoFixture/AutoMoq packages are 2.14.1, Moq is 3.1.416.3, all from NuGet. .NET version is 4.5 (installed with VS2012), behavior is the same in VS2012 and 2010.
While writing this post, I discovered that some people were having problems with Moq 4.0 and assembly binding redirects, so I meticulously purged my solution of any instances of Moq 4 and had Moq 3.1 installed by installing AutoFixture.AutoMoq into "clean" projects. However, the behavior of my test remains unchanged.
Thank you for any pointers and explanations.
Update: Here's the constructor code Mark asked for:
public SettingMappingXml(ISettings settingSource, ITracingService tracing)
{
this._settingSource = settingSource;
this._tracing = tracing;
this.SettingKey = "gcCreditApplicationUsdFieldMappings";
}
And for completeness, the GetXml() method looks like this:
public XElement GetXml()
{
int errorCode = 10600;
try
{
string mappingSetting = this._settingSource.Get(this.SettingKey);
errorCode++;
XElement mappingXml = XElement.Parse(mappingSetting);
errorCode++;
return mappingXml;
}
catch (Exception e)
{
this._tracing.Trace(errorCode, e.Message);
throw;
}
}
SettingKey is just an automatic property.
Assuming that the SettingKey property is defined as follows, I can now reproduce the issue:
public string SettingKey { get; set; }
What happens is that the Test Doubles injected into the SettingMappingXml instance are perfectly fine, but because the SettingKey is writable, AutoFixture's Auto-properties feature kicks in and modifies the value.
Consider this code:
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var sut = fixture.CreateAnonymous<SettingMappingXml>();
Console.WriteLine(sut.SettingKey);
This prints something like this:
SettingKey83b75965-2886-4308-bcc4-eb0f8e63de09
Even though all the Test Doubles are properly injected, the expectation in the Setup method isn't met.
There are many ways to address this issue.
Protect invariants
The proper way to resolve this issue is to use the unit test and AutoFixture as a feedback mechanism. This is one of the key points in GOOS: problems with unit tests are often a symptom about a design flaw rather than the fault of the unit test (or AutoFixture) itself.
In this case it indicates to me that the design isn't fool-proof enough. Is it really appropriate that a client can manipulate the SettingKey at will?
As a bare minimum, I would recommend an alternative implementation like this:
public string SettingKey { get; private set; }
With that change, my repro passes.
Omit SettingKey
If you can't (or won't) change your design, you can instruct AutoFixture to skip setting the SettingKey property:
IMappingXml sut = fixture
.Build<SettingMappingXml>()
.Without(s => s.SettingKey)
.CreateAnonymous();
Personally, I find it counterproductive to have to write a Build expression every time I need an instance of a particular class. You can decouple how the SettingMappingXml instance are created from the actual instantiation:
fixture.Customize<SettingMappingXml>(
c => c.Without(s => s.SettingKey));
IMappingXml sut = fixture.CreateAnonymous<SettingMappingXml>();
To take this further, you can encapsulate that Customize method call in a Customization.
public class SettingMappingXmlCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<SettingMappingXml>(
c => c.Without(s => s.SettingKey));
}
}
This requires you to create your Fixture instance with that Customization:
IFixture fixture = new Fixture()
.Customize(new SettingMappingXmlCustomization())
.Customize(new AutoMoqCustomization());
Once you get more than two or three Customizations to chain, you may get tired of writing that method chain all the time. It's time to encapsulate those Customizations into a set of conventions for your particular library:
public class TestConventions : CompositeCustomization
{
public TestConventions()
: base(
new SettingMappingXmlCustomization(),
new AutoMoqCustomization())
{
}
}
This enables you to always create the Fixture instance like this:
IFixture fixture = new Fixture().Customize(new TestConventions());
The TestConventions gives you a central place where you can go and occasionally modify your conventions for the test suite when you need to do so. It reduces the maintainability tax of your unit tests and helps keep the design of your production code more consistent.
Finally, since it looks as though you are using xUnit.net, you could utilize AutoFixture's xUnit.net integration, but before you do that you'd need to use a less imperative style of manipulating the Fixture. It turns out that the code which creates, configures and injects the ISettings Test Double is so idiomatic that it has a shortcut called Freeze:
fixture.Freeze<Mock<ISettings>>()
.Setup(s => s.Get(settingKey)).Returns(xmlString);
With that in place, the next step is to define a custom AutoDataAttribute:
public class AutoConventionDataAttribute : AutoDataAttribute
{
public AutoConventionDataAttribute()
: base(new Fixture().Customize(new TestConventions()))
{
}
}
You can now reduce the test to the bare essentials, getting rid of all the noise, enabling the test to succinctly express only what matters:
[Theory, AutoConventionData]
public void ReducedTheory(
[Frozen]Mock<ISettings> settingsStub,
SettingMappingXml sut)
{
string xmlString = #"
<mappings>
<mapping source='gcnm_loan_amount_min' target='gcnm_loan_amount_min_usd' />
<mapping source='gcnm_loan_amount_max' target='gcnm_loan_amount_max_usd' />
</mappings>";
string settingKey = "gcCreditApplicationUsdFieldMappings";
settingsStub.Setup(s => s.Get(settingKey)).Returns(xmlString);
XElement actualXml = sut.GetXml();
XElement expectedXml = XElement.Parse(xmlString);
Assert.True(XNode.DeepEquals(expectedXml, actualXml));
}
Other options
To make the original test pass, you could also just switch off Auto-properties entirely:
fixture.OmitAutoProperties = true;
In the first test you can create an instance of the Fixture class with the AutoMoqCustomization applied:
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
Then, the only changes are:
Step 1
// The following line:
Mock<ISettings> settingsMock = new Mock<ISettings>();
// Becomes:
Mock<ISettings> settingsMock = fixture.Freeze<Mock<ISettings>>();
Step 2
// The following line:
ITracingService tracing = new Mock<ITracingService>().Object;
// Becomes:
ITracingService tracing = fixture.Freeze<Mock<ITracingService>>().Object;
Step 3
// The following line:
IMappingXml sut = new SettingMappingXml(settings, tracing);
// Becomes:
IMappingXml sut = fixture.CreateAnonymous<SettingMappingXml>();
That's it!
Here is how it works:
Internally, Freeze creates an instance of the requested type (e.g. Mock<ITracingService>) and then injects it so it will always return that instance when you request it again.
This is what we do in Step 1 and Step 2.
In Step 3 we request an instance of the SettingMappingXml type which depends on ISettings and ITracingService. Since we use Auto Mocking, the Fixture class will supply mocks for these interfaces. However, we have previously injected them with Freeze so the already created mocks are now automatically supplied.
Related
Given the following open generic deocrator chain using SimpleInjector:
container.RegisterManyForOpenGeneric(typeof(IHandleQuery<,>), assemblies);
container.RegisterDecorator(
typeof(IHandleQuery<,>),
typeof(ValidateQueryDecorator<,>)
);
container.RegisterSingleDecorator(
typeof(IHandleQuery<,>),
typeof(QueryLifetimeScopeDecorator<,>)
);
container.RegisterSingleDecorator(
typeof(IHandleQuery<,>),
typeof(QueryNotNullDecorator<,>)
);
With SimpleInjector 2.4.0, I was able to unit test this to assert the decoration chain using the following code:
[Fact]
public void RegistersIHandleQuery_UsingOpenGenerics_WithDecorationChain()
{
var instance = Container
.GetInstance<IHandleQuery<FakeQueryWithoutValidator, string>>();
InstanceProducer registration = Container.GetRegistration(
typeof(IHandleQuery<FakeQueryWithoutValidator, string>));
instance.ShouldNotBeNull();
registration.Registration.ImplementationType
.ShouldEqual(typeof(HandleFakeQueryWithoutValidator));
registration.Registration.Lifestyle.ShouldEqual(Lifestyle.Transient);
var decoratorChain = registration.GetRelationships()
.Select(x => new
{
x.ImplementationType,
x.Lifestyle,
})
.Reverse().Distinct().ToArray();
decoratorChain.Length.ShouldEqual(3);
decoratorChain[0].ImplementationType.ShouldEqual(
typeof(QueryNotNullDecorator<FakeQueryWithoutValidator, string>));
decoratorChain[0].Lifestyle.ShouldEqual(Lifestyle.Singleton);
decoratorChain[1].ImplementationType.ShouldEqual(
typeof(QueryLifetimeScopeDecorator<FakeQueryWithoutValidator, string>));
decoratorChain[1].Lifestyle.ShouldEqual(Lifestyle.Singleton);
decoratorChain[2].ImplementationType.ShouldEqual(
typeof(ValidateQueryDecorator<FakeQueryWithoutValidator, string>));
decoratorChain[2].Lifestyle.ShouldEqual(Lifestyle.Transient);
}
After updating to SimpleInjector 2.6.1, this unit test fails. It seems that InstanceProducer.Registration.ImplementationType now returns the first decoration handler rather than the decorated handler (meaning, it returns typeof(QueryNotNullDecorator<HandleFakeQueryWithoutValidator,string>) instead of typeof(HandleFakeQueryWithoutValidator).
Also, InstanceProducer.GetRelationships() no longer returns all of the decorators in the chain. it also only returns the first decorator.
Is this a bug and, if not, how can we unit test open generic decorator chains using SimpleInjector 2.6.1+?
The detail available for the dependency graph has been greatly improved in 2.6. You can achieve the same thing with this code:
[Fact]
public void RegistersIHandleQuery_UsingOpenGenerics_WithDecorationChain()
{
var container = this.ContainerFactory();
var instance = container
.GetInstance<IHandleQuery<FakeQueryWithoutValidator, string>>();
var registration = (
from currentRegistration in container.GetCurrentRegistrations()
where currentRegistration.ServiceType ==
typeof(IHandleQuery<FakeQueryWithoutValidator, string>)
select currentRegistration.Registration)
.Single();
Assert.Equal(
typeof(QueryNotNullDecorator<FakeQueryWithoutValidator, string>),
registration.ImplementationType);
Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
registration = registration.GetRelationships().Single().Dependency.Registration;
Assert.Equal(
typeof(QueryLifetimeScopeDecorator<FakeQueryWithoutValidator, string>),
registration.ImplementationType);
Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
registration = registration.GetRelationships().Single().Dependency.Registration;
Assert.Equal(
typeof(ValidateQueryDecorator<FakeQueryWithoutValidator, string>),
registration.ImplementationType);
Assert.Equal(Lifestyle.Transient, registration.Lifestyle);
}
You can find more information here
Please note: I think you have a captive dependency - you have a transient handler inside of a singleton decorator ...
[Fact]
public void Container_Always_ContainsNoDiagnosticWarnings()
{
var container = this.ContainerFactory();
container.Verify();
var results = Analyzer.Analyze(container);
Assert.False(results.Any());
}
Qujck is right. We greatly improved the way registrations and KnownDependency graphs are built, especially to improve diagnostics and to make it easier for users to query the registrations. So this is not a bug; this is a breaking change. We however didn't expect anyone to be affected by this and that's why we made the change in a minor release. I'm sorry you had to stumble upon this change, but at least it's just test code that breaks.
In previous versions the graph of KnownDependency objects was flattened when decorators where added. This made querying and visualising the object graph hard. In v2.6, from perspective of the diagnostic API, it is as if a decorator is a 'real' registration. This means that the InstanceProducer and Registration objects now show the real type that is returned and its lifestyle.
Much clearer, but a breaking change in the diagnostic API.
How can the following test be corrected to work?
[TestMethod()]
public void GetEmployeeProductivityTest()
{
var mockHR = new Mock<IRepository<Employee>>();
var mockCMS = new Mock<ICMS_Repository>();
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<string>())).Verifiable();
Employee newEmp = new Employee();
newEmp.User_Name = "testName";
var service = new EmployeeService(mockHR.Object,mockCMS.Object);
var createResult = service.GetEmployeeByUserName(newEmp);
Assert.AreEqual(newEmp, createResult);
mockCMS.VerifyAll();
}
I get the following:
Assert.AreEqual failed. Expected:<Employee>. Actual:<(null)>.
As Requested this is the GetEmployeeByUserName() function being called:
public Employee GetEmployeeByUserName(Employee employee)
{
return _employeeRespository.Find().ByUserName(employee); <------(Using Strict: Gives me the following: All invocations on the mock must have a corresponding setup.)
}
Since you edited your question to show the behaviour of the GetEmployeeByUserName, it's now easy to explain why your test was failing.
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<string>()))
Here you set up an expectation that the FindEmployeeByUsername(string) overload would be called, but then you go on to use the FindEmployeeByUsername(Employee) overload. Moq setups are for specific overloads so when the method is called the mocked service finds no matching setup. If there is no matching setup, the mock either returns the default value for the Employee type (null), or throws an exception, depending on which MockBehavior you chose.
In your updated test, you fixed this by setting up the overload that you actually use.
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<Employee>()))
With simple methods like your GetEmployeeByUserName, mocking the dependencies and unit testing it can seem like a lot of overhead. What your test says is basically,
"when someone calls the GetEmployeeByUserName method on the EmployeeService,
the service should call the correct method on its repository"
Is this an important thing to assert? That's up to you to decide. As the complexity of your service methods increases, however, being able to isolate the dependencies and test their interactions will become more and more valuable.
You need to seed the FindEmployeeByUsername() Method of your mock:
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<string>())).Returns(newEmp);
otherwise it wont return the expected object, while called within the EmployeeService.
Instead of using multiple repositories which I think was confusing. I simplified it and it works now! Except I'm still not sure how this helps me code better. What did I accomplish with this? (I'm new to Testing/Moq/Integration Tests...etc..) I would really like an answer...to this..
public void GetEmployeeUsername_Using_EmployeeClass()
{
var mockCMS = new Mock<ICMS_Repository>(MockBehavior.Strict);
Employee newEmp = new Employee();
newEmp.User_Name = "testName";
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<Employee>())).Returns(newEmp);
var service = new EmployeeService(mockCMS.Object);
var createResult = service.GetEmployeeByUserName(newEmp);
Assert.AreEqual(newEmp, createResult);
}
I am practicing TDD using MsTest together with RhinoMocks, and I am trying to be as lazy as humanly possible, i.e. make use of VS2012 auto-generation wherever I can. But it doesn't always feel right to create an entire test method with the Arrange-Act-Assert methodology, just to set up my class and its constructors and properties.
Currently, I find it easiest to create some properties in my test class - even if I don't use them - solely for the purpose of code generation. My question is, is this a bad habit, and is there a better/easier way to do it? Any commentary, good or bad is welcome; Thank you!
[TestClass]
public class MainViewModelTest
{
private MainViewModel MainViewModel
{
get
{
var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();
var viewModel = new MainViewModel(facilityDataEntity)
{
FacilityValue = string.Empty,
FacilityLabel = string.Empty
};
return viewModel;
}
}
private MainViewModel MainViewModelWithFacilityAndShopOrderData
{
get
{
var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();
var shopOrderDataEntity = MockRepository.GenerateStub<ShopOrderDataEntity>();
var viewModel = new MainViewModel(facilityDataEntity, shopOrderDataEntity)
{
FacilityValue = string.Empty,
FacilityLabel = string.Empty,
ShopOrder = 99999999,
RequiredQuantity = 0M,
ItemCode = string.Empty,
ItemDescription = string.Empty
};
return viewModel;
}
}
[TestMethod]
public void MainViewModel_TranslateDataEntityListMethodReturnsMainViewModelRecords()
{
// Arrange
var facilityDataEntityList = MockRepository.GenerateStub<IEnumerable<FacilityDataEntity>>();
var shopOrderDataEntityList = MockRepository.GenerateStub<IEnumerable<ShopOrderDataEntity>>();
// Act
IEnumerable<MainViewModel> facilityResults = MainViewModel.TranslateDataEntityList(facilityDataEntityList);
IEnumerable<MainViewModel> shopOrderResults = MainViewModel.TranslateDataEntityList(facilityDataEntityList, shopOrderDataEntityList);
// Assert
Assert.IsInstanceOfType(facilityResults, typeof(IEnumerable<MainViewModel>));
Assert.IsInstanceOfType(shopOrderResults, typeof(IEnumerable<MainViewModel>));
}
}
It's not wrong to wrap up common code within your test classes, but I would avoid potentially sharing state between your tests.
There are two approaches you can use here.
Class/Test Initialization
As Peter mentions in his comments, it's easy enough to include initialization methods to do this sort of stuff for you.
//Only runs once per test run
[ClassInitialize]
public void InitClass(){
//Ideally this should be reserved for expensive operations
// or for setting properties that are static throughout
// the lifetime of your test.
}
//Runs for every test
[TestInitialize]
public void TestInit(){
//Here you can setup common stub/mock behavior
// that will be common for every test, but ensure
// it is clean for each test run
}
Setup/Factory Methods
Another option is to create specialized setup or factory methods that can be used to reduce repeated test code and make the intent of your test clearer.
[TestMethod]
public void ShouldFailIfUserNameIsTed(){
var user = SetupUserScenario("Ted");
var result = _myUserService.Validate(user);
Assert.IsFalse(result);
}
private User SetupUserScenario(String username){
var user = new User();
user.Name = username;
//Do a bunch of other necessary setup
return user;
}
Hopefully this all makes sense, but I would also caution you not to go too crazy with this. If you put too much stuff into setup methods, then your tests will be less clear. You should be able to read the test and figure out what is going on without having to inspect a bunch of other places in the code.
That's what the ClassInitialize functionality is for. I would choose expected and recommended means of doing something before anything else. It's more easily recognizable and takes less time to grok the code.
Sometimes I stub dependencies in test class setup and then want to restub some of them in concrete test. But Rhino mocks remembers only the first stub value and it is a bit inconvenient.
someStub.Stub(x => x.SomeMethod(1)).Return(100);
var value1 = someStub.SomeMethod(1);
someStub.Stub(x => x.SomeMethod(1)).Return(200);
var value2 = someStub.SomeMethod(1);
value 2 will be equal to 100.
Is it a designed behaviour? Are there any workarounds?
I ran into a need to do this myself. I worked around it by using the WhenCalled function where you pass in an action to be executed when the function is called. This will give you more flexibility on what you can return at different points.
More info/activity on this stackoverflow thread:
Rhino Mocks: Re-assign a new result for a method on a stub and here:
Changing previously stubbed calls with Rhino Mocks.
I know this is old but hope it helps someone else.
You can work around it with inheritance. If you have a base test class and some test subclasses that run the tests, you can make the return value a protected property of the base test class, and set the value in the subclasses at a point before base. Initialize is called.
So (using MSTEST) you could have:
in your base class:
protected int ReturnVal{get; set;}
public void Init()
{
someStub = MockRepository.GenerateMock<ISomeStub>();
someStub.Stub(x => x.SomeMethod(1)).Return(ReturnVal);
}
in your subclass:
[TestInitialize]
public override Init()
{
ReturnVal = 200;
base.Init();
}
Yes, this is the designed behaviour.
The workaround I use most of the time is to create a helper method that will set up the stub for you, i.e.:
private X MockX()
{
return MockX(100);
}
private X MockX(int returnValue)
{
var x = MockRepository.GenerateStub<X>();
someStub.Stub(x => x.SomeMethod(1)).Return(returnValue);
return x;
}
and then in your test instead of using a mock created in SetUp, you call the appropriate function. The added benefit is that it is clear that your test is using some special values of the return values.
You can use mocks instead of stubs to record a scenario like that:
[Test]
public void Mytest()
{
var mocks = new MockRepository();
var someMock = mocks.DynamicMock<IFoo>();
someMock.SomeMethod(1);
LastCall.Return(100);
someMock.SomeMethod(1);
LastCall.Return(200);
mock.Replay(); // stop recording, go to replay mode
// actual test, normally you would test something which uses the mock here
int firstResult = someMock.SomeMethod(1);
int secondResult = someMock.SomeMethod(2);
// verify the expectations that were set up earlier
// (will fail if SomeMethod is not called as in the recorded scenario)
someMock.VerifyAll();
}
Mocks in Rhino Mocks are more complicated to set up than stubs. They also mix the definition of behavior with the creation of assertions (the record phase does both), and they rely on the ordering of method calls. This makes for brittle tests; stick to stubs unless you really need mocks.
I am trying to test that a method to load a UI matrix is being loaded properly. The test fails unless I tell the mock framework to ignore the argument passed, giving me the following message:
Rhino.Mocks.Exceptions.ExpectationViolationException :
ITimeSheetMatrixWidget.Load
(Smack.ConstructionAdmin.Domain.TransferObjects.TimeSheetDtoAssembler
+d__1); Expected #1, Actual #0.
What is interesting is that the message is somehow picking up a call made to another object that assembles DTOs from the domain model - I don't get it!
Here is the interface / method Sut is:
public interface ITimeSheetMatrixWidget : IMatrixWidget {
.....
void Load(IEnumerable<DynamicDisplayDto>activities);
.....
}
And here is the test:
[Test]
public void SettingTheWidget_TriggersLoad_NonProjectActivities() {
var f = _getFacade();
// create test activities
TestDataFactory.SetupTestActivities(f);
Assert.That(f.NonProjectDtos.Count(), Is.GreaterThan(0));
// create the presenter
var filterService = MockRepository.GenerateStub<IProjectFilterService>();
var view = MockRepository.GenerateStub<ITimeSheetView>();
var timeSheetPresenter = new TimeSheetPresenter(f, filterService, view);
// inject the mocked widget & trigger the Load
var widget = MockRepository.GenerateMock<ITimeSheetMatrixWidget>();
timeSheetPresenter.ActivityMatrix = widget;
widget.AssertWasCalled(x => x.Load(f.NonProjectDtos),
mo =>mo.IgnoreArguments()); <-- ok, but not useful
//widget.AssertWasCalled(x => x.Load(f.NonProjectDtos)); <-- generates the Exception
}
Can someone explain the failure message?
As an aside, I did post this on the Rhino Mocks forum this morning but traffic there looks like it is very low.
Thank you for your help!
Berryl
Rhino was stating the fact that the way the test was laid out, I wasn't getting the call I'd told it to expect. The test below is an effective way to test an IEnumerable argument:
[Test]
public void ProjectMatrix_Injection_IsLoaded()
{
_projectMatrix = MockRepository.GenerateMock<ITimeSheetMatrixWidget>();
var dtos = _facade.ProjectDtos;
_projectMatrix.Expect(x => x.Load(Arg<IEnumerable<DynamicDisplayDto>>.List.Equal(dtos))).Return(dtos.Count());
new MatrixEntryService(_facade, _projectMatrix, _nonProjectMatrix, _totalMatrix);
_projectMatrix.VerifyAllExpectations();
}
The first trick is using the Rhino argument constraints:
Arg<IEnumerable<DynamicDisplayDto>>
The second trick is to use the List extension, instead of Is:
List.Equal(dtos)
I think it expected one call but got none.