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.
Related
I am creating some unit tests for a method ValidateObject in a service ObjectService. The ValidateObject method calls another method ValidateObjectPropertyB. I want to mock the calls to the last method.
The ObjectService and relevant method look like this:
public class ObjectService : IObjectService
{
public bool ValidateObject(object objectToValidate)
{
return
!String.IsNullOrEmpty(objectToValidate.PropertyA) &&
ValidateObjectPropertyB(objectToValidate.PropertyB, currentUserId);
}
public bool ValidateObjectPropertyB(long propertyB, long userId)
{
return validationResult;
}
}
Right now my Test class ObjectServiceTest contains the following code:
public class ObjectServiceTest
{
var objectToValidate = new Object(validPropertyA, validPropertyB);
using(var mock = new AutoMock.GetStrict())
{
var mockObjectService = new Mock<IObjectService>();
mockObjectService.callBase = true;
mockObjectService.Setup(s => s.ValidateObjectPropertyB(objectToValidate.PropertyB, _user.Id)).Returns(true);
var service = mock.Create<ObjectService>();
var result = service.ValidateObject(objectTovalidate);
Assert.IsTrue(result);
}
}
The above test fails because result is false, the for PropertyA succeeds
What am I doing wrong?
ValidateObject works in part by calling ValidateObjectPropertyB. I am presuming you are wanting to mock this second method so that you can demonstrate that ValidateObject does indeed call ValidateObjectPropertyB (provided !String.IsNullOrEmpty(objectToValidate.PropertyA) evaluates to true)
If this is the case then you are testing implementation detail, which generally you shouldn't do. Consider a function that took two integer values and returned their sum, you would want to verify that when this function was passed 3 and 5 it returned 8, you should not test that it arrived at this answer by using a particular method/class under the hood because this is not relevant to the desired outcome and should in future you decide you wished to refactor your code the test would likely start failing even if the code still returned the desired result.
Looking at your code, it seems that return value of ValidateObject is not directly dependent on the method call to ValidateObjectPropertyB but rather the value of validationResult. It is this value that you must set to properly test ValidateObject.
One way to achieve what you are asking would be to make ValidateObjectPropertyB virtual, then create a derived class that overrides this method to return what ever you want. However I do not recommend doing this purely for the sake of unit testing.
I'm using Moq for my Unit Tests and have got the following method:
[TestMethod]
public void GetTestRunById_ValidId_TestRunReturned()
{
var mockTestRunRepo = new Mock<IRepository<TestRun>>();
var testDb = new Mock<IUnitOfWork>();
testDb.SetupGet(m => m.TestRunsRepo).Returns(mockTestRunRepo.Object);
TestRun returnedRun = EntityHelper.getTestRunByID(testDb.Object, 1);
}
The method in question which is being tested is getTestRunByID(). I have confirmed that this method is called when debugging this unit test, but as expected getTestRunByID() doesn't return anything since the mock has no data inside it.
Would all that matter is the method gets hit and returns null? If not, how can I add data to my mockTestRunRepo when it's only present as a returned value from testDb?
For reference the method being tested is:
public static TestRun getTestRunByID(IUnitOfWork database, int testRun)
{
TestRun _testRun = database.TestRunsRepo.getByID(testRun);
return _testRun;
}
The purpose of the unit test is to ONLY test the small method getTestRunByID. For that, test if it was called exactly once with that integer parameters, 1.
mockTestRunRepo.Verify(m => m.getByID(1), Times.Once());
You must also set up the method getByID for mockTestRunRepo, to make it return a specific value, and test if the result value of the test run is equal to what you expected.
//instantiate something to be a TestRun object.
//Not sure if abstract base class or you can just use new TestRun()
mockTestRunRepo.Setup(m => m.getByID(1)).Returns(something);
Test if you get the same value
TestRun returnedRun = EntityHelper.getTestRunByID(testDb.Object, 1);
Assert.AreEqual(returnedRun, something);
This code might be prone to errors, as I do not have an environment to test it right now. But this is the general idea behind a unit test.
This way, you test if the method getById runs as expected, and returns the expected result.
You have your repository return data the same way that you setup everything else.
var mockTestRunRepo = new Mock<IRepository<TestRun>>();
// This step can be moved into the individual tests if you initialize
// mockTestRunRepo as a Class-level variable before each test to save code.
mockTestRunRepo.Setup(m => m.getById(1)).Returns(new TestRun());
Per #Sign's recommendation, if you know that you're calling it with 1, then use that instead of It.IsAny<int>() to keep things cleaner.
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.
Is it acceptable to do asserts in your callbacks if you later verify that the methods were called? Is this the preferred way of making sure my mock is getting the expected parameters passed to it, or should I set a local variable in my callback and do the asserts on that instance?
I have a situation where I have some logic in a Presenter class that derives values based on inputs and passes them to a Creator class. To test the logic in the Presenter class I want to verify that the proper derived values are observed when the Creator is called. I came up with the example below that works, but I'm not sure if I like this approach:
[TestFixture]
public class WidgetCreatorPresenterTester
{
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) =>
Assert.AreEqual("Derived.Name", widget.DerivedName));
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
}
}
I'm concerned because without the Verify call at the end, there is no guarantee that the assert in the callback would be invoked. Another approach would be to set a local variable in the callback:
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
I feel that this approach is less error prone since it is more explicit, and it's easier to see that the Assert statements will be called. Is one approach preferable to the other? Is there a simpler way to test the input parameter passed to a mock that I'm missing?
In case it is helpful, here is the rest of the code for this example:
public class Widget
{
public string Name { get; set; }
public string DerivedName { get; set; }
}
public class WidgetCreatorPresenter
{
private readonly IWidgetCreator _creator;
public WidgetCreatorPresenter(IWidgetCreator creator)
{
_creator = creator;
}
public void Save(string name)
{
_creator.Create(
new Widget { Name = name, DerivedName = GetDerivedName(name) });
}
//This is the method I want to test
private static string GetDerivedName(string name)
{
return string.Format("Derived.{0}", name);
}
}
public interface IWidgetCreator
{
void Create(Widget widget);
}
EDIT
I updated the code to make the second approach I outlined in the question easier to use. I pulled creation of the expression used in Setup/Verify into a separate variable so I only have to define it once. I feel like this method is what I'm most comfortable with, it's easy to setup and fails with good error messages.
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
Expression<Action<IWidgetCreator>> expressionCreate =
(w => w.Create(It.IsAny<Widget>()));
widgetCreator.Setup(expressionCreate)
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(expressionCreate, Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
What I do is do the Verify with matches in keeping with AAA. And becuase of this the Setup is not required. You can inline it but I separated it out to make it look cleaner.
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(MatchesWidget("Derived.Name"));
}
private Widget MatchesWidget(string derivedName)
{
return It.Is<Widget>(m => m.DerivedName == derivedName);
}
Because of the way your code is structured, you're kind of forced to test two things in one unit test. You're testing that A) your presenter is calling the injected WidgetCreator's create method and B) that the correct name is set on the new Widget. If possible, it'd be better if you can somehow make these two things two separate tests, but in this case I don't really see a way to do that.
Given all that, I think the second approach is cleaner. It's more explicit as to what you're expecting, and if it fails, it'd make perfect sense why and where it's failing.
Just to elaborate on #rsbarro's comment - the Moq failure error message:
Expected invocation on the mock at least once, but was never performed
... is less than helpful for complex types, when determining exactly which condition actually failed, when hunting down a bug (whether in the code or unit test).
I often encounter this when using Moq Verify to verify a large number of conditions in the Verify, where the method must have been called with specific parameter values which are not primitives like int or string.
(This is not typically a problem for primitive types, since Moq lists the actual "performed invocations" on the method as part of the exception).
As a result, in this instance, I would need to capture the parameters passed in (which to me seems to duplicate the work of Moq), or just move the Assertion inline with Setup / Callbacks.
e.g. the Verification:
widgetCreator.Verify(wc => wc.Create(
It.Is<Widget>(w => w.DerivedName == "Derived.Name"
&& w.SomeOtherCondition == true),
It.Is<AnotherParam>(ap => ap.AnotherCondition == true),
Times.Exactly(1));
Would be recoded as
widgetCreator.Setup(wc => wc.Create(It.IsAny<Widget>(),
It.IsAny<AnotherParam>())
.Callback<Widget, AnotherParam>(
(w, ap) =>
{
Assert.AreEqual("Derived.Name", w.DerivedName);
Assert.IsTrue(w.SomeOtherCondition);
Assert.IsTrue(ap.AnotherCondition, "Oops");
});
// *** Act => invoking the method on the CUT goes here
// Assert + Verify - cater for rsbarro's concern that the Callback might not have happened at all
widgetCreator.Verify(wc => wc.Create(It.IsAny<Widget>(), It.Is<AnotherParam>()),
Times.Exactly(1));
At first glance, this violates AAA, since we are putting the Assert inline with the Arrange (although the callback is only invoked during the Act), but at least we can get to the bottom of the issue.
Also see Hady's idea of moving the 'tracking' callback lambda into its own named function, or better still, in C#7, this can be moved to a Local Function at the bottom of the unit test method, so the AAA layout can be retained.
Building on top of StuartLC's answer in this thread, you follow what he is suggesting without violating AAA by writing an "inline" function that is passed to the Verify method of a mock object.
So for example:
// Arrange
widgetCreator
.Setup(wc => wc.Create(It.IsAny<Widget>(), It.IsAny<AnotherParam>());
// Act
// Invoke action under test here...
// Assert
Func<Widget, bool> AssertWidget = request =>
{
Assert.AreEqual("Derived.Name", w.DerivedName);
Assert.IsTrue(w.SomeOtherCondition);
Assert.IsTrue(ap.AnotherCondition, "Oops");
return true;
};
widgetCreator
.Verify(wc => wc.Create(It.Is<Widget>(w => AssertWidget(w)), It.Is<AnotherParam>()), Times.Exactly(1));
I am struggling a bit to understand how the new AAA syntax works in Rhino Mocks. Most of my tests look like this:
[Test]
public void Test()
{
//Setup
ISth sth= mocks.DynamicMock<ISth>();
//Expectations
Expect.Call(sth.A()).Return("sth");
mocks.ReplayAll();
//Execution
FunctionBeingTested(sth);
//...asserts, etc
//Verification
mocks.VerifyAll();
}
How would it look like using AAA syntax?
Most probably like this:
[Test]
public void Test()
{
// Arrange
ISth sth= MockRepository.GenerateMock<ISth>();
sth
.Stub(x => x.A())
.Return("sth");
// Act
FunctionBeingTested(sth);
// Assert
}
To really benefit from the new AAA syntax, you have to change your mind a bit. I try to explain.
There is a major difference in my proposal: there is no "Expect-Verify". So I propose to not expect the call, because there is a return value. I assume that the method can't pass the test when it didn't call sth.A, because it will miss the correct return value. It will fail at least one of the other asserts.
This is actually a good thing.
you can move the Stub to TestInitialize, it does not hurt when the stubbed method is not called in a test (it's not an expectation). Your tests will become shorter.
Your test does not know "how" the system under test does the job, you only check the results. Your tests will become more maintainable.
There is another scenario, where you actually need to check if a method had been called on the mock. Mainly if it returns void. For instance: an event should have been fired, the transaction committed and so on. Use AssertWasCalled for this:
[Test]
public void Test()
{
// Arrange
ISth sth= MockRepository.GenerateMock<ISth>();
// Act
FunctionBeingTested(sth);
// Assert
sth
.AssertWasCalled(x => x.A());
}
Note: there is not return value, so there is no Stub. This is an ideal case. Of course, you could have both, Stub and AssertWasCalled.
There is also Expect and VerifyAllExpectations, which actually behaves like the old syntax. I would only use them when you need Stub and AssertWasCalled in the same test, and you have complext argument constraints which you don't want to write twice. Normally, avoid Expect and VerifyAllExpectations
example from Ayende`s blog:
[Test]
public void WhenUserForgetPasswordWillSendNotification_UsingExpect()
{
var userRepository = MockRepository.GenerateStub<IUserRepository>();
var notificationSender = MockRepository.GenerateMock<INotificationSender>();
userRepository.Stub(x => x.GetUserById(5)).Return(new User { Id = 5, Name = "ayende" });
notificationSender.Expect(x => x.Send(null)).Constraints(Text.StartsWith("Changed"));
new LoginController(userRepository, notificationSender).ForgotMyPassword(5);
notificationSender.VerifyAllExpectations();
}
Changes in yours test
[Test]
public void Test()
{
//Arrange
var sth= MockRepository.GenerateMock<ISth>();
sth.Expect(x=>sth.A()).Return("sth");
//Act
FunctionBeingTested(sth);
//Assert
sth.VerifyAllExpectations();
}
But that's just a long shot. Wrote it as i suspect it to be.