Methods to be only available in Unit test - unit-testing

I'm looking for a way to make methods only available in Unit test scripts.
public class MyClass
{
public Data MyData { get; }
internal MyClass()
{
// Complex code setting MyData
}
#if UNITY_MACROS
public MyClass(MyData data)
{
MyData = data;
}
#endif
}
The need is that the public constructor would only be available in the Unit Test scripts and assembly.
I tried to look into Define constraints in the Test assembly but I am probably not using right since I don't see any difference.

What you need is to use the InternalsVisibleTo attribute (MS docs). You can add the following line either in your class source file, or in a separate AssemblyInfo.cs which you can create in the same folder as your asmdef file:
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyUnitTestAssembly")]
In that case you can leave MyClass(MyData data) internal.

Related

Is there a better solution to test getters with the Google Test Framework

I am testing the getters of a class. Each getter has some regex code to validate the input.
I use the Google Test Framework to write the unit tests.
Every time I want to test a new getter I need to expand the parameters of the constructor. I need to update the code of the previous tests to not break the previous tests.
Like this:
TEST_F(wsRecordTest,DoesItThrowExceptionWhenWrongCitynameIsProvided)
{
weatherdayRecord wsRecord{"!#Delft$*"}; --> has to be: weatherdayRecord wsRecord{"!#Delft$*","2020-10-03"};
ASSERT_THROW(wsRecord.getCity(),std::invalid_argument);
}
// Test accessor getDate() and constructor
TEST_F(wsRecordTest,DoIGetTheRightDateFromTheConstructor)
{
weatherdayRecord wsRecord{"Delft","2020-10-03"};
ASSERT_EQ(wsRecord.getDate(),"2020-10-03");
}
Is there a way to avoid this?
How about adding a SetUp functionality to your fixture?
class wsRecordTest : public ::testing::Test {
protected:
std::unique_ptr<weatherdayRecord> record;
void SetUp() override {
record = std::make_unique<weatherdayRecord>("Delft", "2020-10-03");
}
}
TEST_F(wsRecotdTest, CheckDate) {
ASSERT_EQ(record->getDate(), "2020-10-03");
}
Not sure though why you want to test your getters if the classes are just holders for data..

Google mock: Mocking parent class?

Assume I have a base class:
class Command {
public:
virtual int8_t Execute();
};
with a definition in the base class cpp.
Additionally, I have a child class:
class SpecificCommand: public Command {
public:
int8_t Execute();
};
With the definition:
int8_t SpecificCommand::Execute() {
doSomeStuff();
Command::Execute();
}
How do I mock Command::Execute() but using a SpecificCommand object for tests?
Maybe something like that:
class SpecificCommandMock : public SpecificCommand
{
public:
MOCK_METHOD0(ExecuteMockedMethod, void());
int8_t Execute() override
{
doSomeStuff()
ExecuteMockedMethod();
}
}
Of course you should use SpecificCommandMock in unit tests and set EXPECT_CALL for ExecuteMockedMethod when class under test is expected to call Execute().
In addition I suppose that something could be wrong in design of the application if you have to do such things.
This should not be possible in the way you are expecting. I.e. gtest cannot just replace the part of your code and instead of:
int8_t SpecificCommand::Execute() {
doSomeStuff();
Command::Execute();
}
execute something like:
int8_t SpecificCommand::Execute() {
doSomeStuff();
}
You operate with macroses mainly which are just wrap your code with some other. So the language limitation still in there.
Some options (which don't affect your Command implementation):
if doSomeStuff is a public - override the Execute() with mock class as proposed by trivelt or do it like official docs suggests with ON_CALL declaration in mock constructor
write DummyCommand.cpp which do nothing and by compilation option build it instead of original one. In cmake it's if-else + add_library/add_executable manipulations.
write mock to the library which uses "network access that can not be tested" and link it instead of original one by compilation option. (if-else + target_link_library or even include manipulations in the cmake)
write mock for the network communication backend (web_server, etc)

XUnit, RhinoMocks, or TestDriven.Net Issue

Having some issues wrapping my head around class instantiation and TestDriven.Net(v4.0.3478) or XUnit(v2.2.0), RhinoMocks(v3.6.1), and structuremap.automocking(v4.0.0.315).
Given this code:
public class Tests1
{
[Fact]
public void passing_test()
{
var mocker = new RhinoAutoMocker<Subject>();
mocker.Get<IData>().Stub(x => x.Strings).Return(new List<string> {""});
var result = mocker.ClassUnderTest.GetStrings();
result.Count().ShouldEqual(1);
}
}
public class Tests2
{
[Fact]
public void passing_test()
{
var mocker = new RhinoAutoMocker<Subject>();
mocker.Get<IData>().Stub(x => x.Strings).Return(new List<string> {""});
var result = mocker.ClassUnderTest.GetStrings();
result.Count().ShouldEqual(1);
}
}
public class Subject
{
private readonly IData _data;
public Subject(IData data)
{
_data = data;
}
public IEnumerable<string> GetStrings()
{
return _data.Strings;
}
}
public interface IData
{
IEnumerable<string> Strings { get; set; }
}
All tests run fine when I right click -> Run Test(s) on specific test method or a specific class definition.
Tests fail when I right click on project, folder containing tests or the namespace definition of the class above.
The errors are NullReferenceException, when doing asserts, it seems to be the stub's data. It's random, sometimes Tests1.passing_test fails, sometimes Tests2.passing_test fails. Never both.
Thinking it has to with RhinoAutoMocker and/or the MockRepository not being reset between test fixtures?
UPDATE: simplified the code to show the problem, also given code is complete, using NUnit [Test] instead of XUnit [Fact] attributes works, everything behaves as normal.
In your example, you have two separate test classes.
By default, xUnit v2 will run these tests in parallel.
I have experienced the same issue, but in my case using the static MockRepository.GenerateMock.
The static class being used across the parallel tests results in exceptions.
The seeming randomness of the test failures depends on which tests run first.
There are two alternatives I can see.
1. Tests in a single class - not really workable
2. Use the XUnit Collection attribute to place all tests classes in the same collection - this worked for me.
see: http://xunit.github.io/docs/running-tests-in-parallel.html
Another alternative is to turn off parallelism for xUnit using the following attribute in your test assembly
[assembly: CollectionBehavior(DisableTestParallelization = true)]

Replacing PowerMock's #PrepareForTest programmatically?

I am using PowerMock to mock static methods in junit tests, typically done as follows:
#RunWith(PowerMockRunner.class)
#PrepareForTest({Foo.class,Bar.class})
public class SomeUnitTest {
#Before
public void setUpTest() {
setUpFoo();
setUpBar();
}
private void setUpFoo() {
mockStatic(Foo.class);
when(Foo.someStaticMethod()).thenReturn(1);
}
private void setUpBar() {
mockStatic(Bar.class);
when(Bar.someStaticMethod()).thenReturn(2);
}
#Test
public void someTestCase() {
...
}
}
This works fine, but I'm finding that specifying the #PrepareForTest annotation is preventing me from making my testing API flexible.
What I'd like to do is something like the following:
public class MockLibraryOne {
public static void setUpLibraryOne() {
setUpFoo();
setUpBar();
}
private static void setUpFoo() {
mockStatic(Foo.class);
when(Foo.someStaticMethod()).thenReturn(1);
}
private static void setUpBar() {
mockStatic(Bar.class);
when(Bar.someStaticMethod()).thenReturn(2);
}
}
#RunWith(PowerMockRunner.class)
public class SomeUnitTest {
#Before
public void setUpTest() {
MockLibraryOne.setUpLibraryOne();
}
#Test
public void someTestCase() {
...
}
}
Here my unit test has a dependency on LibraryOne, but it does not know which classes LibraryOne depends on, so it does not know which classes to add to the #PrepareForTest annotation.
I could make SomeUnitTest extend MockLibraryOne and add the #PrepareForTest annotation to the MockLibraryOne class, but I will have dependencies on more than just MockLibraryOne in other unit tests, so inheritance is not a general solution.
Is there some way of programmatically preparing a class for testing under PowerMock, instead of using the #PrepareForTest annotation? For example, something like the following:
public class MockLibraryOne {
public static void setUpLibraryOne() {
setUpFoo();
setUpBar();
}
private static void setUpFoo() {
prepareForTest(Foo.class);
mockStatic(Foo.class);
when(Foo.someStaticMethod()).thenReturn(1);
}
private static void setUpBar() {
prepareForTest(Bar.class);
mockStatic(Bar.class);
when(Bar.someStaticMethod()).thenReturn(2);
}
}
I guess it would be nice if PowerMockRunner processed the #PrepareForTest annotation a little differently: for each specified class, it should not only add that class (and its hierarchy) to the list of classes to prepare for mocking, but then examine that class to see if it has any #PrepareForTest annotations as well:
#RunWith(PowerMockRunner.class)
#PrepareForTest({MockLibraryOne.class})
public class SomeUnitTest {
...
}
#PrepareForTest({Foo.class,Bar.class})
public class MockLibraryOne {
...
}
}
So in this the #PrepareForTest annotation on SomeUnitTest would find MockLibraryOne, and the #PrepareForTest annotation there would drag in Foo.class and Bar.class as well.
So perhaps writing my own test runner to replace PowerMockRunner may be a solution.
Or perhaps there's a simpler solution, using PowerMockAgent class, for example?
edit: Mock Policies may be one solution: https://code.google.com/p/powermock/wiki/MockPolicies
edit: Mock Policies works with PowerMockRunner but not (it seems) with PowerMockRule (which I sometimes require due to class loader issues).
What you try to achieve will not work.
The problem is that powermock must rewrite the client class's code to intercept the static invocation and it can't do this after the class is loaded. Thus it can only prepare a class for test before it is loaded.
Let's assume you want to mock the System.currentTimeMillis invocation in the following simple class.
class SystemClock {
public long getTime() {
return System.currentTimeMillis();
}
}
Powermock will not change the code of java.lang.System.currentTimeMillis, because it can't. Instead it changes the SystemClock's byte code so that it does not invoke System.currentTimeMillis anymore. Instead it invokes some other object that belong to powermock.
This is how powermock get's full control over the return value and allows you to write a test like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ SystemClock.class })
public class PowerMockitoTest {
#Test
public void systemTimeMillis() {
SystemClock systemClock = new SystemClock();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.currentTimeMillis()).thenReturn(12345L);
long time = systemClock.getTime();
assertEquals(12345L, time);
}
}
You can see that powermock has rewritten the client class in the stacktrace of your debugger. Set a breakpoint at SystemClock.getTime and step into the invoked method.
As you can see SystemClock invokes a MockGateway.
If you take a look at the variables on the stack of the MockGateway invocation, you can see how the original System.currentTimeMillis method is handled.
Perhaps you're looking for a mock policy?
Could you help this (taken from documentation)?
You can also prepare whole packages for test by using wildcards:
#PrepareForTest(fullyQualifiedNames="com.mypackage.*")
So you can add the whole library to your prepare...
Why do you even want to mock static methods? Why not wrap those static methods in a class that you can mock with mockito?
class FooWraper {
void someMethod() {
Foo.someStaticMethod()
}
}
and then you can create a mock of your FooWraper. No need to use Powermock at all...

How to mock static member variables

I have a class ClassToTest which has a dependency on ClassToMock.
public class ClassToMock {
private static final String MEMBER_1 = FileReader.readMemeber1();
protected void someMethod() {
...
}
}
The unit test case for ClassToTest.
public class ClassToTestTest {
private ClassToMock _mock;
#Before
public void setUp() throws Exception {
_mock = mock(ClassToMock.class)
}
}
When mock is called in the setUp() method, FileReader.readMemeber1(); is executed. Is there a way to avoid this? I think one way is to initialize the MEMBER_1 inside a method. Any other alternatives?
Thanks!
Your ClassToMock tightly coupled with FileReader, that's why you are not able to test/mock it. Instead of using tool to hack the byte code so you can mock it. I would suggest you do some simple refactorings to break the dependency.
Step 1. Encapsulate Global References
This technique is also introduced in Michael Feathers's wonderful book : Working Effectively with Legacy Code.
The title pretty much self explained. Instead of directly reference a global variable, you encapsulate it inside a method.
In your case, ClassToMock can be refactored into this :
public class ClassToMock {
private static final String MEMBER_1 = FileReader.readMemeber1();
public String getMemberOne() {
return MEMBER_1;
}
}
then you can easily using Mockito to mock getMemberOne().
UPDATED Old Step 1 cannot guarantee Mockito mock safely, if FileReader.readMemeber1() throw exception, then the test will failled miserably. So I suggest add another step to work around it.
Step 1.5. add Setter and Lazy Getter
Since the problem is FileReader.readMember1() will be invoked as soon as ClassToMock is loaded. We have to delay it. So we make the getter call FileReader.readMember1() lazily, and open a setter.
public class ClassToMock {
private static String MEMBER_1 = null;
protected String getMemberOne() {
if (MEMBER_1 == null) {
MEMBER_1 = FileReader.readMemeber1();
}
return MEMBER_1;
}
public void setMemberOne(String memberOne) {
MEMBER_1 = memberOne;
}
}
Now, you should able to make a fake ClassToMock even without Mockito. However, this should not be the final state of your code, once you have your test ready, you should continue to Step 2.
Step 2. Dependence Injection
Once you have your test ready, you should refactor it further more. Now Instead of reading the MEMBER_1 by itself. This class should receive the MEMBER_1 from outside world instead. You can either use a setter or constructor to receive it. Below is the code that use setter.
public class ClassToMock {
private String memberOne;
public void setMemberOne(String memberOne) {
this.memberOne = memberOne;
}
public String getMemberOne() {
return memberOne;
}
}
These two step refactorings are really easy to do, and you can do it even without test at hand. If the code is not that complex, you can just do step 2. Then you can easily test ClassToTest
UPDATE 12/8 : answer the comment
See my another answer in this questions.
UPDATE 12/8 : answer the comment
Question : What if FileReader is something very basic like Logging that needs to
be there in every class. Would you suggest I follow the same approach
there?
It depends.
There are something you might want to think about before you do a massive refactor like that.
If I move FileReader outside, do I have a suitable class which can read from file and provide the result to every single class that needs them ?
Beside making classes easier to test, do I gain any other benefit ?
Do I have time ?
If any of the answers is "NO", then you should better not to.
However, we can still break the dependency between all the classes and FileReader with minimal changes.
From your question and comment, I assume your system using FileReader as a global reference for reading stuff from a properties file, then provide it to rest of the system.
This technique is also introduced in Michael Feathers's wonderful book : Working Effectively with Legacy Code, again.
Step 1. Delegate FileReader static methods to instance.
Change
public class FileReader {
public static FileReader getMemberOne() {
// codes that read file.
}
}
To
public class FileReader {
private static FileReader singleton = new FileReader();
public static String getMemberOne() {
return singleton.getMemberOne();
}
public String getMemberOne() {
// codes that read file.
}
}
By doing this, static methods in FileReader now have no knowledge about how to getMemberOne()
Step 2. Extract Interface from FileReader
public interface AppProperties {
String getMemberOne();
}
public class FileReader implements AppProperties {
private static AppProperties singleton = new FileReader();
public static String getMemberOne() {
return singleton.getMemberOne();
}
#Override
public String getMemberOne() {
// codes that read file.
}
}
We extract all the method to AppProperties, and static instance in FileReader now using AppProperties.
Step 3. Static setter
public class FileReader implements AppProperties {
private static AppProperties singleton = new FileReader();
public static void setAppProperties(AppProperties prop) {
singleton = prop;
}
...
...
}
We opened a seam in FileReader. By doing this, we can set change underlying instance in FileReader and it would never notice.
Step 4. Clean up
Now FileReader have two responsibilities. One is read files and provide result, another one is provide a global reference for system.
We can separate them and give them a good naming. Here is the result :
// This is the original FileReader,
// now is a AppProperties subclass which read properties from file.
public FileAppProperties implements AppProperties {
// implementation.
}
// This is the class that provide static methods.
public class GlobalAppProperties {
private static AppProperties singleton = new FileAppProperties();
public static void setAppProperties(AppProperties prop) {
singleton = prop;
}
public static String getMemberOne() {
return singleton.getMemberOne();
}
...
...
}
END.
After this refactoring, whenever you want to test. You can set a mock AppProperties to GlobalAppProperties
I think this refactoring would be better if all you want to do is break the same global dependency in many classes.
Powermock core provides a convenient utility method that could be used for this purpose.
Add powermock-core to your project.
testImplementation group: 'org.powermock', name: 'powermock-core', version: '2.0.9'
FileReader fileReader = mock(FileReader.class);
Whitebox.setInternalState(ClassToMock.class, "MEMBER_1", fileReader);
Whitebox.setInternalState is just a convenient method to set the value of a field using reflection. So it could be used along with any Mockito tests.