Nsubstitute intercept hard dependency - unit-testing

I am unit testing legacy code and I am dealing with a class that instantiates another class. I believe this is testable using Microsoft Fakes, but am wondering if NSubstitute has the capability. I believe the answer is no, but need to be sure.
public class ClassA
{
public int MethodA()
{
int reportId = this.MethodB();
return reportId;
}
public virtual int MethodB()
{
ClassC c = new ClassC();
return c.MethodA();
}
}
public class ClassC
{
public virtual int MethodA()
{
return 2;
}
}
[Test]
public void Test_ClassA()
{
ClassA subclassA = new ClassA();
var subclassC = Substitute.For<ClassC>(); //this is pointless the way I have it here
subclassC.MethodA().Returns(1); //this is pointless the way I have it here
int outValue = subclassA.MethodA();
Assert.AreEqual(outValue, 1); //outvalue is 2 but I would like it to be 1 if possible using Nsubstitute
}

It is possible to override virtual methods in classes by using partial substitution: just make sure that the base code cannot be called by specifying that the base class must not be called:
var A = Substitute.ForPartsOf<ClassA>();
var C = Substitute.ForPartsOf<ClassC>();
C.When(c => c.MethodA()).DoNotCallBase();
C.MethodA().Returns(10);
A.When(a => a.MethodB()).DoNotCallBase();
var cResult = C.MethodA();
A.MethodB().Returns(cResult);
Console.WriteLine(A.MethodB());
Console.WriteLine(C.MethodA());

Related

references are a pain for my mocks in TDD

I am new with c++/tdd, embraced gtest/gmock, and fell in love.
One thing kind of puzzles me though. Are reference pointers really the way to go?
I find myself producing a lot of boiler plate injecting all mocks (even when I don't have any business mocking that behavior).
Example:
namespace
{
class set_configuration_command_tests : public testing::Test
{
protected:
void SetUp() override
{
_uart_peripheral = new uart8_peripheral_mock();
_uart = new uart8_mock(*_uart_peripheral);
_logger = new logger_mock(*_uart);
_mqtt_client = new mqtt_client_mock(*_logger);
_set_configuration_command = new set_configuration_command(*_mqtt_cient);
}
void TearDown() override
{
delete _set_configuration_command;
}
uart8_peripheral_mock *_uart_peripheral;
uart8_mock *_uart;
logger_mock *_logger;
mqtt_client_mock *_mqtt_cient;
set_configuration_command *_set_configuration_command;
};
TEST_F(set_configuration_command_tests, execute_update_configuration)
{
// arrange
// act
// assert
}
}
What I rather did here, is create my sut as
_mqtt_client = new mqtt_client_mock(nullptr); // will not compile of course
_set_configuration_command = new set_configuration_command(*_mqtt_cient);
All the other mocks, I don't need in this case.
Is this the drawback of using reference pointers? Or is there a better approach I should follow?
Found a better alternative. Providing interfaces (pure virtual classes) heavily reduces the need to provide an entire tree of mocks.
e.g
class flash_api : public iflash_api
{
public:
flash_api(iflash_peripheral &flash_peripheral) : _flash_peripheral(flash_peripheral)
{
}
virtual ~flash_api()
{
}
}
Before my mock inherited from flash_api directly. When I gave this class an interface too (`iflash_api') I can let my mock inherit from iflash_api, which gives me a parameter-less constructor.
class flash_api_mock : public iflash_api
{
public:
flash_api_mock()
{
}
virtual ~flash_api_mock()
{
}
}
Then I can write my unit test based on the mocks I actually want to give behavior.
class set_configuration_command_tests : public testing::Test
{
protected:
void SetUp() override
{
_mqtt_cient = new mqtt_client_mock();
_flash_api = new flash_api_mock();
_set_configuration_command = new set_configuration_command(*_mqtt_cient, *_flash_api);
}
void TearDown() override
{
delete _set_configuration_command;
}
flash_api_mock *_flash_api;
mqtt_client_mock *_mqtt_cient;
set_configuration_command *_set_configuration_command;
};

How to mock config file for unit test

I have a class in which there is a parameter less constructor. But when this constructor is called, there are five properties of the class that gets values from config file in the constructor. There are two method in the class which uses the parameters that get initialized in the constructor.
I want to write unit test for two methods using mock framework. But, I am not sure of how to initialize the parameters in the constructor as calling the method will not provide the value to those properties.
public class ABC
{
public ABC()
{
a = ConfigurationManager.AppSetting["GetValue"];
b = ConfigurationManager.AppSetting["GetValue1"];
}
public int Method1(IDictionary<string, string> dict)
{
d = a + b /2; (how to mock values of a and b while writing unit tests
using mock framework. In reality, a in my case is
dictionary)
//some business logic
return d;
}
}
Thanking in advance,
You cannot Mock values of a and b as your code is tightly coupled with app.config file. You can create an interface. Refactor code like below to inject an interface to you constructor and then mock it,
public class ABC
{
private int a;
private int b;
public ABC(IConfig config)
{
a = config.a;
b = config.b;
}
public int Method1(IDictionary<string, string> dict)
{
int d = a + b / 2;
return d;
}
}
public interface IConfig
{
int a { get; }
int b { get; }
}
public class Config : IConfig
{
public int a => Convert.ToInt32(ConfigurationManager.AppSettings["GetValue"]);
public int b => Convert.ToInt32(ConfigurationManager.AppSettings["GetValue1"]);
}
And in you test class Mock and inject IConfig like below,
Mock<IConfig> _mockConfig = new Mock<IConfig>();
_mockConfig.Setup(m => m.a).Returns(1);
_mockConfig.Setup(m => m.b).Returns(2);
ABC abc = new ABC(_mockConfig.Object);
Now your code is decoupled with app.config and you will get mock values of a and b while running unit test.

Unit testing classes that use dagger 2 to create objects

Let's say I have a dagger 2 module as follows,
#Module
interface Creator {
MyClass create();
}
and I am using it to create an instance of MyClass
class Instantiator {
void doSomething(){
MyClass clazz = DaggerCreator.create().create();
// do things with clazz
}
}
It seems to me that I cannot effectively test the doSomething method in Instantiator because I cannot provide a mock for MyClass.
Am I wrong? If not are we supposed to use Dagger instantiation sparingly?
You are correct in saying that it is hard to test use of a Component injector, since this is a static method. But harder than what? Here is the same method using instantiation:
class Instantiator {
void doSomething(){
MyClass clazz = new MyClass();
// do things with clazz
}
}
still hard to test, right?
The point is to use as few Component (injectors) as possible and to pass in dependencies in the constructor for your objects. Dagger 2 makes resolving the dependencies in the constructor easy. This thereby makes testing easy since you can pass in mock object in a constructor.
Let's refactor the code you wrote to be testable. Assume that MyClass contains a single method, fireLazers() that you want to test is being invoked inside Instantiator's doSomething() method:
public class DoerOfSomething {
private final MyClass myClass;
#Inject
public DoerOfSomething(MyClass myClazz) {
this.myClass = myClazz;
}
public void doSomething() {
myClass.fireLazers();
}
}
Now you can write a test like this using a mock object:
public void DoerOfSomethingTest {
//mocks
MyClass mockMyClass;
//system under test
DoerOfSomething doerOfSomething;
#Before
public void setUp() {
mockMyClass = Mockito.mock(MyClass.class);
}
#Test
public void whenDoSomething_thenInteractsWithMyClass() {
//arrange
doerOfSomething = new DoerOfSomething(mockMyClass);
//act
doerOfSomething.doSomething();
//assert
verify(mockMyClass).fireLazers();
}
}
Of course, you will now need to inject DoerOfSomething into the top level class where you are injecting, but now you can be certain that the object you are injecting is functioning as expected because it is testable. Your code for using Dagger looks a bit unusual but I'll use your idioms for the sake of parity between the question and the answer.
class Instantiator {
private final DoerOfSomething doerOfSomething;
Instantiator() {
doerOfSomething = DaggerCreator.create().create();
}
void doSomething() {
doerOfSomething.doSomething();
}
}

Invalid setup on a non-overridable member:

I'm trying to test the function GetcallEntityBycallEntity (Guid callId) with Mock library.
this function calls another class that does not implement any interface.
protected virtual CallFacade CallFacade()
{
return new CallFacade();
}
public Note GetCallEntityByCallEntity(Guid CallEntity)
{
myCall= null;
**CallFacade** callFacade = Get CallFacade();
if (CallEntity!= Guid.Empty)
{
myCall = callFacade.GetCallByEntityId(CallEntity);
}
return myCall;
}
CallFacade Not is an Interface
in my test:
[TestInitialize]
public void TestInitialization()
{
IoCMocks.Initialize();
CommonCallFacadeMock = new CommonCallFacadeMock();
}
public void GetCallEntityByNoteEntity_GetCall_ReturnValidCall()
{
//Arrange
CallmyNote = GetmyCall(); //private method. == Call.CreateCall();
//Stubs
CommonCallFacadeMock.MockCallFacade.Setup(x => x.GetCallByEntityId(ExistingCallEntity)).Returns(myCall);
//Action
var obtained = CommonCallFacadeMock.GetCallEntityByCallEntity(ExistingCallEntity);
CommonCallFacadeMock.MockCallFacade.Verify(x => x.GetCallByEntityId(It.IsAny<Guid>()), Times.Once());
}
You get this error message because MOQ can mock only interfaces, abstract methods or properties on abstract classes, virtual methods or properties on concrete classes.
You have to mark method GetCallByEntityId as virtual.
There is an old discussion in "Moq Discussions" google group about virtual methods.

Unit Testing Moq not passing through method when virtual

Hi say I have some code like:
public class Class1
{
public int MyMethod()
{
return MyOtherMethod();
}
public virtual int MyOtherMethod()
{
return 1;
}
}
Ok, this doesn't do much of relevance but this is just for a simple example.
I then create a new test:
[TestMethod]
public void TestMethod1()
{
var t = new Mock<Class1>();
var w = t.Object.MyMethod();
}
Could someone please tell me why the code runs through the called method MyOtherMethod when it's not designated as virtual but when you make it virtual the test code refuses to go through that method?
You should setup the virtual method before you calling MyMethod:
t.Setup(c => c.MyOtherMethod()).Return(1);