Reputation: 25830
In Java, when I have a class that calls some other class' static method, I always encapsulate this so I can test it without actually hitting that real resource. For example:
public class HasSomeStaticCall
{
public HasSomeStaticCall()
{
this.something = callStaticThing();
}
protected String callStaticThing()
{
return SomeThirdParty.getFromStaticMethod();
{
}
In Java, I can then use Spy
instead of Mock
and then use all the real methods except for that one.
Example:
public void test()
{
HasSomeStaticCall obj = Mockito.spy( HasSomeStaticCall.class );
//Only mock this one method
Mockito.doReturn( "SomeValue" ).when( obj ).callStaticThing();
}
How would I do this in C#? (I'm using the .Net Framework 4.7.x, not .Net Core)
Upvotes: 9
Views: 8949
Reputation: 538
With C# mocking frameworks, you do not have a concept like a spy. What you can do is to create a mock and arrange it to call the original code where your method that calls the static method can return the value you desire. You should have in mind that the free C# mocking frameworks will work only with interfaces and virtual methods. So if your case is to arrange a public virtual method that returns a value than here is how this could be done. I will use the free version JustMock for the next examples:
HasSomeStaticCall obj = Mock.Create<HasSomeStaticCall>(Behavior.CallOriginal);
Mock.Arrange(() => obj.callStaticThing()).Returns("SomeValue");
var actual = obj.callStaticThing();
Assert.AreEqual("SomeValue", actual);
JustMock has a commercial version that allows you to mock non-public methods like the protected method in your code. Here is how the arrangement should look like for such a method:
HasSomeStaticCall obj = Mock.Create<HasSomeStaticCall>(Behavior.CallOriginal);
Mock.NonPublic.Arrange<string>(obj, "callStaticThingProtected").Returns("SomeValue");
var actual = obj.MethodThatCallsTheProtectedcallStaticThing();
Assert.AreEqual("SomeValue", actual);
Of course, there should be a way to call the protected method. This is why I have used the MethodThatCallsTheProtectedcallStaticThing. However, it is not required if you have another way of executing this method.
I have noticed that in your scenario you are actually setting the value of a field in the constructor with the result from the method that calls the static method. Most of the C# mocking frameworks will allow you three possible options to handle the constructor execution: Calling the original constructor, Not calling the constructor and do something else instead of calling the constructor. Neither of them allows you to arrange some of the instance methods of your HasSomeStaticCall class in advance before creating the mock. This is a problem as the constructor is doing stuff you would like to preserve. JustMock allows you to mock static methods. Here is an example for your scenario:
Mock.Arrange(() => SomeThirdParty.getFromStaticMethod()).Returns("SomeValue");
HasSomeStaticCall obj = new HasSomeStaticCall();
var actual = obj.Something;
Assert.AreEqual("SomeValue", actual);
I have created a Something property to access the value of the field which is not required if you have another way to verify the value when needed.
If you are interested in JustMock you could check the feature comparison table for JustMock and JustMock Lite
Disclaimer. I am one of the developers responsible for JustMock.
Upvotes: 6