Coming from using Moq, I'm used to being able to Setup mocks as Verifiable. As you know, this is handy when you want to ensure your code under test actually called a method on a dependency.
e.g. in Moq:
// Set up the Moq mock to be verified
mockDependency.Setup(x => x.SomethingImportantToKnow()).Verifiable("Darn, this did not get called.");
target = new ClassUnderTest(mockDependency);
// Act on the object under test, using the mock dependency
target.DoThingsThatShouldUseTheDependency();
// Verify the mock was called.
mockDependency.Verify();
I've been using VS2012's "Fakes Framework" (for lack of knowing a better name for it), which is quite slick and I'm starting to prefer it to Moq, as it seems a bit more expressive and makes Shims easy. However, I can't figure out how to reproduce behavior similar to Moq's Verifiable/Verify implementation. I found the InstanceObserver property on the Stubs, which sounds like it might be what I want, but there's no documentation as of 9/4/12, and I'm not clear how to use it, if it's even the right thing.
Can anyone point me in the right direction on doing something like Moq Verifiable/Verify with VS2012's Fakes?
-- 9/5/12 Edit --
I realized a solution to the problem, but I'd still like to know if there's a built-in way to do it with VS2012 Fakes. I'll leave this open a little while for someone to claim if they can. Here's the basic idea I have (apologies if it doesn't compile).
[TestClass]
public class ClassUnderTestTests
{
private class Arrangements
{
public ClassUnderTest Target;
public bool SomethingImportantToKnowWasCalled = false; // Create a flag!
public Arrangements()
{
var mockDependency = new Fakes.StubIDependency // Fakes sweetness.
{
SomethingImportantToKnow = () => { SomethingImportantToKnowWasCalled = true; } // Set the flag!
}
Target = new ClassUnderTest(mockDependency);
}
}
[TestMethod]
public void DoThingThatShouldUseTheDependency_Condition_Result()
{
// arrange
var arrangements = new Arrangements();
// act
arrangements.Target.DoThingThatShouldUseTheDependency();
// assert
Assert.IsTrue(arrangements.SomethingImportantToKnowWasCalled); // Voila!
}
}
-- 9/5/12 End edit --
Since I've heard no better solutions, I'm calling the edits from 9/5/12 the best approach for now.
EDIT
Found the magic article that describes best practices. http://www.peterprovost.org/blog/2012/11/29/visual-studio-2012-fakes-part-3/
Although it might make sense in complex scenarios, you don't have to use a separate (Arrangements) class to store information about methods being called. Here is a simpler way of verifying that a method was called with Fakes, which stores the information in a local variable instead of a field of a separate class. Like your example it implies that ClassUnderTest calls a method of the IDependency interface.
[TestMethod]
public void DoThingThatShouldUseTheDependency_Condition_Result()
{
// arrange
bool dependencyCalled = false;
var dependency = new Fakes.StubIDependency()
{
DoStuff = () => dependencyCalled = true;
}
var target = new ClassUnderTest(dependency);
// act
target.DoStuff();
// assert
Assert.IsTrue(dependencyCalled);
}
Related
I'm trying to setup unit testing for my API controllers. I'm using the mediatr pattern and FakeIteasy.
I have the following code.
public class ChannelGroupChannelsControllerTests
{
private readonly ChannelGroupChannelsController _controller;
private readonly IMediator _mediator;
public ChannelGroupChannelsControllerTests()
{
var service = A.Fake<IReadChannelGroupChannel>();
var mapper = A.Fake<IMapper>();
var channelGroupChannel = new ChannelGroupChannel
{
Id = 1,
ChannelGroupId = 1,
ChannelId = 1,
Channel = new Channel { Name = "Channel Name" }
};
_mediator = A.Fake<IMediator>();
_controller = new ChannelGroupChannelsController(_mediator, mapper);
A.CallTo(() => _mediator.Send(A<GetChannelGroupChannelById>._, A<CancellationToken>._)).Returns(channelGroupChannel);
}
[Fact]
public async Task ChannelGroupChannelsController_ById()
{
var result = await _controller.ById(1);
(result.Result as StatusCodeResult)?.StatusCode.Should().Be((int)HttpStatusCode.OK);
result.Value.Should().BeOfType<ChannelGroupChannelVM>();
}
}
Now the problem is that I keep getting NULL as a value.
I think the issue might be that GetChannelGroupChannelById has a constructor that expects the ID. But I'm not sure...
Does anybody know what could be wrong? I'm pretty new with the mocking stuff.
Kind regards
I'm not familiar with mediatr, so may be off base here, and it would be much easier to answer this question if we saw what your controller was doing. If you're able, please supply the code, as without that insight, I'm left to guess a little, but I'll try.
If GetChannelGroupChannelById's constructor expects an ID (an int?), FakeItEasy will provide an ID when it makes the Fake version. If it's an int, FakeItEasy will provide a 0, unless you've done some very fancy configuration you've not shown us. If that's supposed to line up with some other value in your code and doesn't, it may cause your problem.
Otherwise, I see you have a Fake IMapper, that is never configured, but is passed into the controller. I'm guessing this is supposed to translate some values. An unconfigured Fake will return a dummy value (or default if no dummy value can be made). It's possible that this unconfigured mapper is interrupting your flow.
(I also see that service in the test class constructor is unused. I would remove it or use it. It may not be part of your problem, but it's at least distracting.)
I'm trying to test a private method on a mocked object. Please, calm down, I know you're getting your pitchforks out.
I'm well aware everything about to say can be answered by yelling REFACTOR at me. I just need a straight answer. Someone look me in the eyes and tell me this can't be done. It's an ungoogleable problem, so I just need to hear it.
Here's what I'm dealing with.
public class SecretManager
{
protected virtual string AwfulString { get { return "AWFUL, AWFUL THING"; }
public SecretManager()
{
//do something awful that should be done using injection
}
private string RevealSecretMessage()
{
return "don't forget to drink your ovaltine";
}
}
Here's me trying to test it.
var mgr = new Mock<SecretManager>();
mgr.Protected().SetupGet<string>("AwfulThing").Returns("");
var privateObj = new PrivateObject(mgr.Object);
string secretmsg = privateObj.Invoke("RevealSecretMessage");
Assert.IsTrue(secretmsg.Contains("ovaltine"));
and the exception:
System.MissingMethodException: Method 'Castle.Proxies.SecretManagerProxy.RevealSecretMessage' not found
Is what I'm trying to do, mad as it is, possible? Or is this simply too much hubris for a unit test to bear?
You're trying to call a method on the proxy that Castle created. The proxy won't have access to the private method on the class that it inherits from because, well, the method is private. Remember that Castle.Proxies.SecretManagerProxy is actually a subclass of SecretManager.
Do you really need a mock of SecretManager? I realize your code is a slimmed down abstract of the real code, but it seems the only thing you're doing with the mock is setting up a return for a property that isn't used by the method you're trying to test anyway.
var privateObj = new PrivateObject(mgr.Object, new PrivateType(typeof(SecretManager)));
string secretmsg = privateObj.Invoke("RevealSecretMessage");
It will work by specifying PrivateType for the PrivateObject.
Your code should be following for what you are trying to test. You don't need to mock the SecretManager and SetGet "AwfulThing" as you are not using it.
var privateObj = new PrivateObject(new SecretManager());
string secretmsg = (string)privateObj.Invoke("RevealSecretMessage", new object[] { });
Assert.IsTrue(secretmsg.Contains("ovaltine"));
But ideally you shouldn't be testing Private methods. See below article for the explanation:
http://lassekoskela.com/thoughts/24/test-everything-but-not-private-methods/
I'm trying to work out why some of my test cases (using RhinoMocks 3.6 Build 20) aren't working, and I've narrowed the issue down to the following minimal unit test:
public interface ITest
{
string Something { get; }
}
[Test]
public void TestStub()
{
var mockery = new MockRepository();
var testItem = mockery.Stub<ITest>();
testItem.Stub(x => x.Something).Return("Hello");
Assert.AreEqual("Hello", testItem.Something);
}
This fails with the message:
Expected: "Hello" But was: null
Any ideas what I'm doing wrong here? I've found a few examples on SO and the Rhino Wiki on how to stub read-only properties, and as far as I can tell, this should work fine.
Cheers in advance.
EDIT: Based on sll's advice below, I tried replacing
testItem.Stub(x => x.Something).Return("Hello");
with
testItem.Expect(x => x.Something).Return("Hello");
and the test still fails in the same manner.
Edit 2: I've got this working by adding the line
mockery.ReplayAll();
before the Assert - but I thought this was no longer required (from the wiki: "Mocks/stubs returned from MockRepository.GenerateMock() and MockRepository.GenerateStub() are returned in replay mode, and do not require explicit move to replay mode.")
Try out generating Mock instead:
var testItem = MockRepository.GenerateMock<ITest>();
testItem.Expect(x => x.Something).Return("Hello");
Assert.AreEqual("Hello", testItem.Something);
Als make sure you shared entire test method, perhaps you ignored some lines of code?
Try out usign Repeat.Any() perhaps proeprty accessed before you are doing expectation.
testItem.Expect(x => x.Something).Return("Hello").Repeat.Any();
On example page Stub() used for methods, and suggested using Mock's Expect() for properties:
Using Expect() to set up properties
The Expect() extention method can be used to set up expectations and
return values for properties.
Got it:
From the RhinoMocks 3.6 Blog Post comments:
09/03/2009 05:34 PM by
Kurt Harriger
FYI,
I had a few dozen tests fail after upgrading to v 3.6 from code like this:
var mocks = new MockRepository();
var something = mocks.Stub
something.Stub(x=>x.DoSomething() ).Return(true);
something.DoSomething();
The root cause of the problem appears that mock.Stub/Mock/etc no longer returns the mock in replay mode. To fix replaced mock.Stub with MockRepository.GenerateStub.
Ayende Rahien
09/03/2009 06:50 PM by
Ayende Rahien
Kurt,
That is actually expected, that should have never worked
So, by changing the test to:
[Test]
public void TestStub()
{
var testItem = MockRepository.GenerateStub<ITest>();
testItem.Stub(x => x.Something).Return("Hello");
Assert.AreEqual("Hello", testItem.Something);
}
this now works.
Cheers
You are just setting the value so you would expect to do this like this:
public interface ITest
{
string Something { get; }
}
[Test]
public void TestStub()
{
var mockery = new MockRepository();
var testItem = mockery.Stub<ITest>();
testItem.Something = "Hello";
Assert.AreEqual("Hello", testItem.Something);
}
No need to Stub with Func.
I'm trying to become more familiar with the Rhinomocks framework, and I'm trying to understand the Expect methods of rhinomocks.
Here's a unit test I have written:
[TestMethod]
public void Create_ValidModelData_CreatesNewEventObjectWithGivenSlugId()
{
//Arrange
var eventList = new List<Event>() { new Event() { Slug = "test-user" } };
_stubbedEventRepository.Stub(x => x.GetEvents())
.Return(eventList);
_stubbedEventRepository
.Expect(x => x.SaveEvent(eventList.SingleOrDefault()))
.Repeat
.Once();
var controller = new EventController(_stubbedEventRepository);
EventViewModel model = new EventViewModel();
//Act
//controller.Create(model); COMMENTED OUT
//Assert
_stubbedEventRepository.VerifyAllExpectations();
}
I thought I understood this code to only pass if the SaveEvent(...) method get's called exactly once. However, with controller.Create(model) commented out, the test still passes. Inside controller.Create(model) is where the SaveEvent() method gets called.
I tried the following:
_stubbedEventRepository
.Expect(x => x.SaveEvent(eventList.SingleOrDefault()));
But it still passes every time, so what am I doing incorrectly stack overflow? The sources I have looked at online haven't been able to help me. Why is VerifyAllExpectations() yielding a successful unit test?
Thank you!
Here's the body of the controller constructor:
public EventController(IEventRepository eventRepository)
{
_eventRepository = eventRepository;
}
edit:
// member variables
private IEventRepository _stubbedEventRepository;
[TestInitialize]
public void SetupTests()
{
_stubbedEventRepository = MockRepository.GenerateStub<IEventRepository>();
}
If you want to verify the behavior of the code under test, you will use a mock with the appropriate expectation, and verify that. If you want just to pass a value that may need to act in a certain way, but isn't the focus of this test, you will use a stub.
I'm still trying to get my head around mocking. Right now, I'm trying to test my Save method on my UserService. As such, I'm mocking out my IRepository which my UserService class uses.
What I don't get is... if i normally save this user to my DB/Repository, it magically gets an Identity, which it then gets set, into my instance object. No rocket science stuff, here.
What I don't understand is, how do i mock this? should I care? I thought I should. Or.. is it that i don't care about that .. because I'm just making sure that the Repository method is called .. not so much that I get the correct data BACK from it.
Here's my pseudo unit test code. (unit test, not integration test .. hence the mock'd repository)...
[TestMethod]
public void GivenANewUserWithValidData_Save_ReturnsTheSameNewUserWithAUserIdDetermined()
{
// Arrange.
var const string passwordSalt = "V4BXAhmHq8IMvR7K20TgoQ=="
var user = new User
{
DisplayName = "Test",
Email = "foo#foo.com",
PasswordSalt = passwordSalt ,
Password = "foobar".ToSha2Hash(passwordSalt)
};
var mockUserRepository = new Mock<IRepository<User>>();
mockUserRepository.Setup(x => x.Save(It.IsAny<User>())).Verifiable();
// Configure this repo in our Dependency Injection.
ObjectFactory.Inject(typeof (IRepository<User>), mockUserRepository.Object);
// Act.
using (new TransactionScope())
{
UserService.Save(user);
UnitOfWork.Commit(); // <-- not sure about this.. currently it's still
// an EntityFramework context.
// I need to change this to.. something??
// Assert.
Assert.IsNotNull(user);
Assert.IsTrue(user.UserId > 0);
}
}
and the user service looks like this..
public class UserService : IUserService
{
public UserService(IRepository<User> userRepository,
ILoggingService loggingService)
{
// .. snip ..
public void Save(User user) { .. }
}
}
Any suggestions?
If you are unit testing UserService.Save(), then all your test should care about is that the repository is called. It's the responsibility of the repository tests to verify that an object is saved correctly.
That's actually something easy to do. You're setting up the Mock object like so:
mockUserRepository.Setup(x => x.Save(user)).Callback(() => user.UserId = 10);
// mocking the value of 10 being insterted into the key
You can even continue using It.IsAny() if you want in the setup, but basically all you need to do is attach the callback to the end of your setup method.
> 1) How should I test a [UserService.]Save method?
Should I care about the result? and
> 2) If i do care about #1 .. then how do i mock the
result also, so I can test that
If the repository is responsible to do the Identity-Magic then it makes no sense to mock this functionality in a test and then verify that this functionality has happened in the test. You want to test the UserService and not the IRepository-mock. The mock is there to crate a fake repository with just enought intelligence that the service does not crash and gets all requirements for the testcase. In this case I do not think that Identity-Magic is required by the service.
If the service is responsible to do the Identity-Magic then it makes sence to test if the id has been set.