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(){}
Related
In our ASP.Net core application, we have many APIs which are calling public method from the service class.
Service class is implementing an Interface.
Each service method (depending upon complexity and requirement) may call any number of internal or private or helper methods.
While each of these internal/private/or helper methods are separately unit tested, how do we test the public service methods in such a way that we don't have to duplicate the code/effort that we have already spent in testing the internal/private/helper methods?
e.g. we can easily mock up the Interface methods to say the interface method expects these input arguments and returns bla bla (without actually calling the method). So, can a similar thing be done to internal/private/helper methods which are not part of Interfaces so that we don't have to actually call these methods real time, and can just 'Mock' them while testing the main method itself?
Well, actually you can mock your internal/private methods if they are virtual.
For example, having class like:
public class ClassUnderTest
{
public void MethodUnderTest() {
SubMethod();
}
protected virtual void SubMethod() {
}
}
You can mock it and test with:
var classMock = new Mock<ClassUnderTest>();
classMock.Setup(x => x.SubMethod());
var class = classMock.Object;
class.MethodUnderTest();
classMock.Verify(x => x.SubMethod(), Times.Once);
Still, it's not actually good approach. Usually, if you need to test such scenario, that means that your MethodUnderTest and class ClassUnderTest actually works as orchestrator for other functions and there is certain sense in extracting methods (that are called from MethodUnderTest) from ClassUnderTest to other classes to keep your architecture SOLID. ClassUnderTest will perform orchestration, while others classes will do there work.
BTW. Another bad thing is that if you mark your internal methods as protected virtual just to have ability to mock them, that a bit violates idea of unit-testing, where you should not add any special code to make it testable.
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")]
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)