I have a class which is responsible for building PPT slides for exporting. To unit test this I have created an interface so it can be mocking using Moq; all great so far. However I run into difficulties when trying to test that my method has been called. It is a void method so at this point I only want to know that the method has been hit.
Here is my interface:
interface IPowerpointExporter
{
void AddSlides(int amount);
void setTitle(string title);
}
And here's my unit test:
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
mockPPT.Object.AddSlides(1);
mockPPT.VerifyAll();
}
However when I come to call AddSlides() I get a GeneratorException. The explanation for this is that my IPowerpointExporter was not accessible. I have a feeling this is because I am trying to call a method on an interface, though I'm unsure since I've got my object at mockPPT.Object.AddSlides(); at this point.
Note that I've also tried the following trying to use an actual object rather than Interface.Object. This also gives the same exception:
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
mockPPT.VerifyAll();
}
Using Moq how can I check that my method has been called? Is what I'm doing above along the right lines?
You're likely getting that exception because your interface is not public, or otherwise visible to the Moq assembly. See this question to resolve that.
If this is just dummy code to help you learn Moq, then read no further.
However, if this an actual test that you think has value, then you have other more fundamental issues. In your first example, you're doing absolutely nothing to test your code! Let's go through it, line by line:
var mockPPT = new Mock<IPowerpointExporter>();
You created a mock of your IPowerpointExporter interface, so far so good.
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
You told the mock to expect a call to it's AddSlide method, with an argument of 1, and that the method can be verified. No problem so far.
mockPPT.Object.AddSlides(1);
But here's where it goes off the rails. You're just invoking the method on your mock, the same one you just setup above. The Object property is a dummy object, it can only do what it was setup to do and has no ties to your actual implementation!
mockPPT.VerifyAll();
Now you verified that you called all your verifiable methods. All you did in this test was verify that Moq works; your code was never touched.
Let's look at the changed code in your second example now:
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
That cast will never work. The Object property is just some proxy (a dynamic type actually), generated by Moq that knows nothing about any concrete implementation of the interface it is mocking.
This exception occurs because IPowerpointExporter interface is not accessible to Moq.
You can make your IPowerpointExporter interface public, and test runs perfectly:
public interface IPowerpointExporter
{
void AddSlides(int amount);
void setTitle(string title);
}
....
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
mockPPT.VerifyAll();
}
However, when you need make tests to non-public types, you can use InternalsVisibleTo attribute in your assembly to make types visible to Moq.
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
How do you set up debugging so that you can step through your system under test code?
I've got this test:
[Test]
public void GetDeviceSettings_is_called()
{
//Arrange
var mockDeviceInteractions = new Mock<IDeviceInteractions>();
mockDeviceInteractions.SetupSet(p => p._settingsFileQueue = It.IsAny<string>());
mockDeviceInteractions.Setup(x => x.GetDeviceSettings(It.IsAny<string>(), It.IsAny<string>()));
//Act
mockDeviceInteractions.Object._settingsFileQueue = #"C:\";
mockDeviceInteractions.Object.GetDeviceSettings("123123", "dfgdfg");
//Assert
mockDeviceInteractions.VerifyAll();
}
and here's the method I'm acting on:
public virtual DeviceSettings GetDeviceSettingsForSerialNumber(string serial) {
//do stuff - and i've put a break point here, but it does not step at the break point
GetDeviceSettings(string1, string2);
//do more stuff
}
What am I doing wrong? Why does it not stop at the breakpoint?
You must mock the objects which will be called by the class under test, not the class itself.
Here's an example. It assumes you can inject dependencies into your classes.
Imagine you are writing a nuclear control system. You want to check that the system will instruct the reactor to perform an emergency shutdown when it needs to, by writing a unit test.
public enum ReactorStatus { Ok, OhDear};
public interface IReactorInteractions {
ReactorStatus ShutDown(bool nicely);
ReactorStatus Status { get; }
}
public interface ICore {
ReactorStatus ShutDown(bool nicely);
ReactorStatus GetStatus();
}
public class ReactorInteractions : IReactorInteractions {
private ICore reactor;
public ReactorInteractions(ICore reactor) {
this.reactor = reactor;
}
public ReactorStatus ShutDown(bool nicely) {
return reactor.ShutDown(nicely);
}
public ReactorStatus Status {
get { return reactor.GetStatus(); }
}
}
So, you want to test the ReactorInteractions class.
In order to do this, then, you mock the object that it calls, in this case ICore. You do not want to perform operations on the actual Core. Doing so would surely be a disciplinary offence, at the very least!
You should pass the Object property of the ICore mock as the constructor parameter to the ReactorInteractions class - this property is not something that you should be accessing in your test, it is designed solely to be passed to the class under test - it is this 'Object' that the class under test acts on, allowing you to use Setup and Verify:
private Mock<ICore> mockCore;
private IReactorInteractions reactor;
[SetUp]
public void TestSetup() {
mockCore = new Mock<ICore>();
reactor = new ReactorInteractions(mockCore.Object);
}
So some example tests (which if they were real tests would be validating and checking worthwhile things - tests should check logic, not plumbing.):
[Test]
public void ShutDown_Nicely_Should_Pass() {
mockCore.Setup(m => m.ShutDown(true).Returns(ReactorStatus.Ok));
var status = reactor.ShutDown(true);
status.Should().Be(ReactorStatus.Ok);
mockCore.VerifyAll();
}
[Test]
public void ShutDown_Badly_Should_Fail() {
mockCore.Setup(m => m.ShutDown(false).Returns(ReactorStatus.OhDear));
var status = reactor.ShutDown(false);
status.Should().Be(ReactorStatus.OhDear);
mockCore.VerifyAll();
}
Note that I am not using It.IsAny<bool> in my test setup. This syntax is verry confusing for developers new to mocking (seen in the wild: trying to use It.IsAny as parameters in test calls) - which is something that I wish the Moq author would highlight in the documentation. It.IsAny should only be used if you have absolutely no control over the parameter.
In your case, there's no need to use It.IsAny - you know exactly what values you're going to pass:
const string serial = "123456";
mockDeviceInteractions.Setup(m => m.GetDeviceSettingsForSerialNumber(string serial))
.Returns(new DeviceSettings { Serial = serial };
var settings = classUnderTest.GetDeviceSettingsForSerialNumber(serial);
settings.Serial.Should.Be(serial);
Then in the test, you are checking that the actual value is used. If you test for It.IsAny then bear in mind that the part of your code that deals with that value could be replaced with a random number generator and the unit test would still pass.
Having said that, Moq has had the limitation that if one argument in the list is unknown and must use It.IsAny then they all must be (I'm not using it any more so I don't know if that's still the case, but I seem to remember you could work around that anyway by using a callback to validate the parameters manually)
To answer the question,
How do you set up debugging so that you can step through your system under test code?
There is no particular setup that you have to do that would be any different from debugging a system running from the Start button in Visual Studio.
A unit test is effectively just code that stresses the public API of a class. The only difference between the unit test and an actual call to the public API is the fact that you have some attributes to add to the method and that you mock dependencies within the class.
The class itself remains the same as it does when debugging normally but you have setup scenarios for it to handle different logic which you can then verify occurred correctly.
To get your test runner to run the test in debug you'll have to select it to run in debug otherwise most runners default to running in what is basically release mode. Depending on the runner that you are using this is accomplished differently, but most usually allow you to right-click the test to debug and select something along the lines of Debug the selected Tests.
Addressing your next question,
What am I doing wrong? Why does it not stop at the breakpoint?
When you are running a unit test as described above you are testing the actual class but are setting up scenarios that the logic implemented must handle correctly.
The main issue is that you don't look as though you are ever calling the method you are expecting to run, the test never calls GetDeviceSettingsForSerialNumber(...) unless this is called by the setting of the property which you haven't described.
What you have actually done is to mock the system under test therefore not actually testing the implemented code, but basically testing that moq works correctly. This can be identified by this line:
mockDeviceInteractions.Setup(x => x.GetDeviceSettings(It.IsAny<string>(), It.IsAny<string>()));
You are mocking the call to GetDeviceSettings(string, string), I'm not sure on the implementation of this method but if the method is marked as virtual moq will in the background create a new overridden method which will be called when any string is provided as the arguments.
You are then calling:
mockDeviceInteractions.Object.GetDeviceSettings("123123", "dfgdfg");
moq in the background is receiving this call and the interceptor is matching this to one of the setup calls (see above), it will then call the setup call which neither does anything nor returns anything.
If the method you are trying to test 'GetDeviceSettingsForSerialNumber' is called when the property (I hope this isn't a field you are calling) is set this is nullified when you setup the property with the call:
mockDeviceInteractions.SetupSet(p => p._settingsFileQueue = It.IsAny<string>());
I've never attempted this but I don't believe that it will run the actual property setter in the class which may be what you are looking for.
If you wanted to setup the property to have default value you are able to say:
mock.SetupProperty(f => f.Name, "foo");
Now I could explain why I feel that what you are testing is incorrect, but I feel that #stuartd answer covers how a class should be structured in having dependencies which you can mock to return data instead of mocking calls within the system under test. I will instead show you how I would structure your actual test with the structure you have just now.
[Test]
public void GetDeviceSettings_is_called()
{
//Arrange
var mockDeviceInteractions = new Mock<IDeviceInteractions>();
var deviceSettings = new Mock<IDeviceSettings>();
mockDeviceInteractions.Setup(x => x.GetDeviceSettings(#"123123", "dfgdfg"))
.Returns(deviceSettings.Object)
.Verifiable();
//Act
var actual = mockDeviceInteractions.Object.GetDeviceSettingsForSerialNumber(#"123123");
//Assert
Assert.Equal(deviceSettings.Object, actual);
mockDeviceInteractions.Verify();
}
First off I have removed you SetupSet for the property, this is not required, if you want to set the actual property just set it on the object, I also removed the property being set as I couldn't see how this fit in with your test, unless you are expecting that method to be called from the property setter which you haven't described.
Next up I have added a Returns method call to your Setup of the GetDeviceSettings, I wasn't sure what this returned but as you can see it returns a IDeviceSettings in my example and I have also marked this as Verifiable.
I then call the actual GetDeviceSettingsForSerialNumber from thee object. You never called this at all so I'm not surprised that you couldn't hit a breakpoint.
Finally I am asserting that the IDeviceSettings returned from the call is the same as the one that the GetDeviceSettings method returned. I know this is slightly different from your implementation as you return a concrete DeviceSettings but this should actually return an interface.
Lastly I am verifying the mockDeviceInteractions as you can see with the Verify call and not the VerifyAll call as I occasionally setup a mock with calls that I don't necessary want to Verify and only the mark the ones that I do want to Verify with the correct method call.
I'm trying to unit test a method and mock the method call inside it:
class LoginViewModel
{
public bool LogUserIn(string hashedPassword)
{
//Code
if (loginSuccessful)
{
GoToMainMenu(); // I WANT TO MOCK THIS CALL.
return true;
}
return false;
}
}
so I want to mock the GoToMainMenu() function call, as this is only for navigation and I get an exception thrown here when I try to run my test.
I've tried using NUnit.Mocks:
[Test]
public void Log_User_In_Will_Return_True()
{
DynamicMock mockView = new DynamicMock(typeof(LoginViewModel));
mockView.ExpectAndReturn("GoToMainMenu", null);
LoginViewModel loginVM = (LoginViewModel)mockView.MockInstance; //ArgumentException
Assert.AreEqual(true, loginVM.LogUserIn("aHashedPassword"));
}
But this gives me an ArgumentException.
I've spent a lot of time trying different ways to make this work and have also tried Rhino Mocks but couldn't get my head around how to mock this call. Can anyone help with this? I haven't tried Moq but suspected it to be similar to Rhino Mocks.
In your current setup this what you're trying to do is impossible. Few things to fix:
start using stable version of Rhino (like 3.6). Better yet, upgrade to Moq which is a newer framework
make GoToMainMenu method virtual (and at least protected)
Your test then (Rhino 3.6) should look like this:
var mock = MockRepository.GenerateMock<LoginViewModel>();
Assert.AreEqual(true, mock.LogUserIn("aHashedPassword"));
Few things to note here. Any non-virtual method called will use your original implementation (like LogUserIn). Every virtual method on the other hand will be replaced by RhinoMocks with default (do nothing) implementation, which should be enough to make test pass. The same test in Moq:
var mock = new Mock<LoginViewModel>();
Assert.AreEqual(true, mock.Object.LogUserIn("aHashedPassword"));
The way it works like this (need to have virtual methods) is because when creating a mock, both Rhino and Moq will generate in memory assembly and create new type there, deriving from your type (in your case, LoginViewModel). Derived type (mock) can then replace any method of original type given it's virtual (standard C# mechanism) or type is interface - then the mock simply implements the interface.
public Class Test{
GetDataset(RandomBoolean uncertain);
GetDataset2();
GetDataset3();
}
where method definitions are
public virtual void GetDataset2(){}
public virtual void GetDataset3(){}
public virtual void GetDataset(RandomBoolean uncertain)
{
if (uncertain.State){
GetDataset2();
}
else{
GetDataset3();
}
}
//mocking uncertain.State to return true
//ACT
testObject.GetDataset(uncertainMock);
I want to test if GetDataset2() was called internally when I act on testObject.GetDataset();
I am not mocking the testObject because it's the test object so if I try to do
testObject.AssertWasCalled(x => x.GetDataset2());
It won't let me do this because testObject is not a mocked object.
I am using Rhino Mocks 3.5, I am definitely missing something here.
What is the best way to achieve this.
The short answer is: you can't. On the other thing usually you don't want to. When you are unit testing the class, you want to make sure that the class does its computation correctly and that it has correct side effects. You shouldn't test the internals of the class, because this causes the coupling of the real code and the tests to be too strong. The idea is that you can freely change the implementation of your class and use your tests to make sure it still works correctly. You wouldn't be able to do it if your tests inspect the internal state or flow.
You have 2 options (depending on context)
You can structure your tests in a way that they only look at externally visible behaviour
If (1) is too hard, consider refactoring GetDataset2 into a separate class. Then you would be able to mock it while testing GetDataset method.
That's generally not how unit testing with mocks works.
You should be concerned with collaborators (which you stub/mock) and with results (state changes in the case of void methods), not with the internal workings of the system under test (calls to collaborators notwithstanding).
That is both because and why you can't make those types of behavioural observations (at least not without changing your classes to accommodate testing, by exposing private members or adding state-revealing members -- not good ideas).
Besides using a partial mock via Rhino Mocks, you could also create class derived from Test that replaces the implementation of GetDataSet2() with a function that records it was called. Then check that in your test.
It is a code smell that you're doing too much in one class though.
There is some info about partial mocks here. Here are some code snippets on how to do that with RhinoMocks and Moq.
Try this:
using Rhino.Mocks;
public class TestTest {
[Test]
public void FooTest()
{
var mock = new MockRepository().PartialMock<Test>();
mock.Expect(t => t.GetDataset2());
mock.GetDataset((RandomBoolean)null);
}
}
I use RhinoMocks for a very simple test (I have to say I'm a beginner here). I tried to mock my object like this
var mock = MockRepository.GenerateMock<MyClass>();
create a helper stub :
var stubLinkedObject = MockRepository.GenerateStub<MyClass>();
then execute some logic which should call the method AddLink of the class MyClass with my stub argument. At the end of the test I simply assert that this method was actually called with
mockAction.AssertWasCalled(a => a.AddLink(stubLinkedObject));
I injected the correct dependency and the method is actually called. However, the problem is that the real implementation in MyClass is called and results in crash because some logic just can't be executed (link collection is not available etc.). How can I bypass the execution and simply check whether a method is called ? I have tried something like
mockAction.Stub(a => a.AddLink(null)).IgnoreArguments().Do(null);
before I go into the execution but this doesn't seem to work(I only get some exceptions). Any ideas and probably an explanation why the mock is executing the method logic at all ?
I've tried to reproduce. Here is the code which works fine for me
[Test]
public void Test()
{
var classMock = MockRepository.GenerateMock<MyClass>();
var linkedMock = MockRepository.GenerateStub<MyClass>();
classMock.Expect(c => c.MyMethod(linkedMock));
classMock.MyMethod(linkedMock);
classMock.AssertWasCalled(c => c.MyMethod(linkedMock));
}
public class MyClass
{
public virtual void MyMethod(MyClass linkedClass)
{
Console.WriteLine("MyMethod is called");
}
}
Your approach will only work if your method AddLink is virtual, otherwise the .Net runtime will always run the real implementation (and rightly so).
Usually the best practise is to use interfaces when doing dependency injection (so your class expects IMyClass instead of MyClass). This way it is much easier to use mocking frameworks - not only you don't have to remember to make all methods virtual, but you avoid the issues with passing correct arguments to MyClass's constructor (which in real world is a pain)
I have a class that acts like this at the moment:
public class MyClass {
public void Method1(){
if (false) {
Method2();
}
}
public void Method2(){
//do something here
}
}
So Method2 is never called (my code looks a bit different but I have this if-clause that evaluates to false and therefore doesn't execute the Method2. Checked it by debugging to be sure). I want to tell RhinoMocks that I expect Method2 to be called and the test to fail:
MockRepository mock = new MockRepository();
MyClass presenter = mock.PartialMock<MyClass>();
Expect.Call(() => presenter.Method2()).IgnoreArguments();
mock.ReplayAll();
presenter.Method1();
mock.VerifyAll();
...but the test passes.
(The reason for the lambda expression in the Expect.Call is, that my actual Method2 has arguments)
My questions:
Is this the usual approach for testing in this scenario? (I'm just starting with RhinoMocks and mocking-frameworks in general)
Why does the test pass?
As confirmed by Jakob's comments, PartialMock only mocks abstract/virtual methods, so your expectation isn't actually doing anything.
Personally I don't generally mock out methods within the class I'm testing. I just mock out dependencies, and express those through interfaces instead of concrete classes, avoiding this problem to start with.
I think there is a lot of value in partially mocking out concrete classes. Say for example you have a couple private methods that get called within a class. You obviously would need to make them 'internal' before testing, but you would like to have a way to test this -- without making a new class (which isn't the right solution in a lot of cases).
To make this test fail you would just have the signature of Method 2 to:
public virtual void Method2(){}