问题
I am writing a unit test case with NUnit framework to test our code.
The code has referenced to 3rd party libraries like below:
class MyClass: BaseClass
{
public void override FunctionA()
{
var a = BaseFunctionB();
}
}
we don't have sourcecode for BaseClass
, but the BaseFunctionB
is non-virtual.
I was trying to
Setup(x=> x.BaseFunctionB()).Reteruns("my values");
but it doesn't allow.
I just want to test the FunctionA
in MyClass
, I don't care whether it's correct in BasefunctionB
.
How to test in this case?
----------------------------2018-01-03 updated---------------------------------
I made some update for the BaseClass
:
public abstract class BaseClass1//we dont have source code for this class
{
public int GetValue()
{
//do something here
return 1;//
}
public abstract int GenerateOutPut();
}
class abstract class BaseClass2: BaseClass1
{
public new virtual int GetValue()
{
return base.GetValue();
}
}
class MyClass1: BaseClass2
{
public override int GenerateOutPut()
{
var a = GetValue();
a += 1;
return a;
}
}
class MyClass2: BaseClass2
{
public override int GenerateOutPut()
{
var a = GetValue();
a -= 1;
return a;
}
}
// there are many MyClass
class MyClassN: BaseClass2
{
public override int GenerateOutPut()
{
var a = GetValue();
//different logic here.
return a;
}
}
i made a class for testing MyClass1
like below:
class TestClass1: MyClass1
{
public override int GetValue()
{
return 100;
}
}
test case as below:
public void TestFunction()
{
var test = new TestClass1();
var result = test.GetValue();
assert.AreEqual(101, result);
}
Now I have to create many TestClas
which looks not good. but in terms of running out code coverage, i have to make it( i try to use mock object to execute, there is no code covered in report, i guess because it create proxy and run it on proxy, so i create the same thing myself to test the original source code)
Do i have a better solution?
回答1:
Creating the second base class and the new member to encapsulate the 3rd party dependency was a good idea. It allows you to override the member in derived classes. In general try to avoid mocking what you do not own. Instead encapsulate 3rd party dependencies behind an abstraction you control so as to allow you the flexibility to mock/stub/fake any desired behavior for testing.
Using MyClass1
from your example
public class MyClass1 : BaseClass2 {
public override int GenerateOutPut() {
var a = GetValue();
a += 1;
return a;
}
}
The following test can be done to verify the expected behavior from the subject under test. Note Moq allows for base members to be called by setting CallBase = true
on the mocked object.
[TestClass]
public class MyClass1_Test {
[TestMethod]
public void MyClass1_Should_Generate_Output() {
//Arrange
var expected = 0;
var mock = new Mock<MyClass1>() {
CallBase = true //<-- let mock call base members
};
mock.Setup(_ => _.GetValue()).Returns(expected); // <-- mocked behavior
var sut = mock.Object; //<-- subject under test.
//Act
var actual = sut.GenerateOutPut();
//Assert
actual.Should().Be(expected + 1);
}
}
Which is almost like what you did manually but now via the mock proxy.
来源:https://stackoverflow.com/questions/48057304/c-sharp-mock-return-base-method