I have a class (class A) to which I define an extension function (A.extension()) inside a companion object of another class (class B) for a matter of organization.
On my tests I need:
To use a real class A instance .
To mock A.extension().
To use a mock instance of class B.
Using MockK-library I am not being able to mock that extension function successfully.
I've tried:
mockkObject(B.Companion) {
every { any<A>().extension() } returns whatIneed
}
result: Tries to run the unmocked version of the extension function.
mockkStatic(path.to.B.CompanionKt)
every { any<A>().extension() } returns whatIneed
Result: It does not find the Companion Object.
mockkStatic(A::extension) {
every { any<A>().extension() } returns whatIneed
}
Result: Compile error -> 'extension' is a member and an extension at the same time. References to such elements are not allowed.
Am I missing something regarding how to mock this ?
Am I doing something wrong in terms of code structuring that prevents this mocking to be possible?
Any help is appreciated.
This seems to be an impossible thing. I have tried this severally and it does not work.
Related
I'm having an issue with mocking a class with a companion object using mockito. It looks similar to this
#Component
class Util {
companion object {
fun generateName(job: Job) {
return job.name + "_" + (System.currentTimeMillis()/100L).toString()
}
}
}
I am trying to mock this class so I can do something like this:
I mocked the utility in test file like
var util : Util.Companion = mock()
Now inside my test I want to do the following:
#Test
fun "test function"() { //(dont have the symbols, not using the work laptop, excuse the syntax error)
whenever(util.generateName(job)).thenReturn("mystring")
}
Since our job names contain timestamps, I need this to work otherwise my unit tests won't work. Needless to say, this whenever is not working and my functions return the "correct" result when mocked, instead of the one I want provided in the return clause, otherwise during inserts I will always get nulls since I can't mock the timestamps. Please don't suggest different mocking libraries and such, there's already almost 100 tests written with mockito, so that is not an option.
You need to mock creating the companion object, which means compiler creates empty constructor of the class and use that constructor to create the companion object of that class.
You need specifically to return mocked object whenever the constructor is called, i.e new instance for that calls is created.
This doesn't play well with Mockito. I won't suggest you PowerMockito, that's like shooting yourself in the stomach.
I have an extension method which is used to read a particular claim from the current ClaimsPrincipal. But I also need to check this value against a list of items which I have in the appsettings.json.
I had this working by using a ConfigurationBuilder() to read the appsettings directly in much the same way as the startup does, although instead of using
.SetBasePath(Directory.GetCurrentDirectory())
as I do in the startup, I was using
.SetBasePath(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location))
Which although isn't pretty, works fine.
However, when the Unit tests are run none of the following get me to where the appsettings are
Directory.GetCurrentDirectory()
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
and I cannot see a way of getting the IHostingEnvironment or something similar into the extension method to read out the appsettings, or indeed to ditch the ConfigurationBuilder() and get at IOptions in the extension method, in such a way that the unit test and the running code will work correctly.
I assume there must be a way of doing this? Although I expect that I should simply not be trying at all and lift the check against the list of items into another class entirely...
Putting business logic that may ever require dependencies into static methods is not recommended. This makes it difficult to inject dependencies into them. Options are few:
Redesign the static method into a service so dependencies can be injected through the constructor. (Recommended)
public class Foo : IFoo
{
private readonly IOptions<FooOptions> optionsAccessor;
public Foo(IOptions<FooOptions> optionsAccessor)
{
this.optionsAccessor = optionsAccessor ??
throw new ArgumentNullException(nameof(optionsAccessor));
}
public void DoSomething()
{
var x = this.optionsAccessor;
// Same implementation as your static method
}
}
Inject the dependencies as parameters of the extension method.
public static void DoSomething(this object o, IOptions<FooOptions> optionsAccessor)
{
// Implementation
}
Redesign the static method to be a facade over an abstract factory like this example.
I'm using inject-loader to mock dependencies for a Typescript project being unit tested. The service I'm testing has an import line like this:
import pnp, { SearchQuery, Sort, SortDirection, CamlQuery } from "sp-pnp-js";
For my test, I want to mock several of the functions on pnp, but keep the classes intact. In my unit test file, I've included this import:
import { SearchQuery, Sort, SortDirection, CamlQuery } from "sp-pnp-js";
Which gives my test access to the necessary classes. I've declared a mock service object:
// mock services
const mockPnp = {
default: { ... }
};
Which I'm wiring into my target class instance:
Service = require("inject!./sharepointservice")({
"sp-pnp-js": mockPnp
}).Service;
And everything works, so long as I don't run any code that references those classes (ie. SearchQuery). To get that to work, I tried adding it to the mock:
// mock services
const mockPnp = {
default: { ... },
SearchQuery: SearchQuery
};
However, I get a 'SearchQuery' only refers to a type, but is being used as a value here error.
I've tried casting to any (same error), tricks with modules and exports, with no luck. I'm supposed to be able to write any Javascript with Typescript, and this would work trivially in Javascript - what am I missing here?
According to the definition file SearchQuery is an interface, which means that you can not treat it as a value (as the error message says).
Typescript interfaces aren't being compiled into the js output, and you can not use them at runtime.
Technically, since its just for type safety, I can do this
t: MyInterface = {};
Is it possible to create a mock of non-existing class in PHPUnit?
Let's assume I have some class that creates instance of another class, for example:
class TaskRunner
{
public function runTasks()
{
// Run through some loop to get tasks and store each in $taskName
// Get task instance by given task name
$task = $this->getTaskInstance($taskName);
if ($task instanceof AbstractTask) {
$task->run();
}
}
protected function getTaskInstance($taskName)
{
// Just an example
return new $taskName();
}
}
I would like to run unit test for runTasks method to check if created task instace extends some abstract class.
Is there any possibility to NOT to create sample class in a filesystem to check the inheritance constraint?
Thanks for all!
Yes, it is possible to stub/mock classes that do not exist with PHPUnit. Simply do
$this->getMockBuilder('NameOfClass')->setMethods(array('foo'))->getMock();
to create an object of non-existant class NameOfClass that provides one method, foo(), that can be configured using the API as usual.
Since PHPUnit 9, you shall replace :
'NameOfClass' by \stdClass::class
setMethods by addMethods
$this->getMockBuilder(\stdclass::class)->addMethods(array('foo'))->getMock();
The accepted answer is perfect, except that since PHPUnit 9 there is an issue, if you need to mock a class that is required to be of a certain instance. In that case \stdclass::class cannot be used.
And using
$this->getMockBuilder('UnexistentClass')->addMethods(['foo'])->getMock();
will result in Class UnexistentClass does not exist, because addMethod checks the given methods against the given class methods.
In case anybody else is having the same issue, luckly setMethods still works, so this still works in PHPUnit 9
$this->getMockBuilder('UnexistentClass')->setMethods(['foo'])->getMock();
Note though that setMethods will be removed in PHPUnit 10
Hopefully at that time there will be a fix for this issue. Like for example checking if allowMockingUnknownTypes is set to true. If that check is implemented this will then work too:
$this->getMockBuilder('UnexistentClass')->allowMockingUnknownTypes()
->addMethods(['foo'])->getMock();
I'm trying to create a unit test for a code similar to this:
foreach (string domainName in Directory.GetDirectories(server.Path))
{
HandleDomainDirectory(session, server, domainName);
}
The problem is that I'm using the System.IO.Directory class in my code.
How can I create a testing method that won't be dependent on any folder I have on my hard disk.
In other words, How can I fake the response of "Directory.GetDirectories(server.Path)"?
(Please note, I do control the "server" object in my class, therefore i can give any path i want)
Thanks.
Rather than calling Directory.GetDirectories(server.Path) directly, you could create an interface like IDirectoryResolver with a single method that takes a path string and returns the list of directories. The class containing your code above would then need a property or field of type IDirectoryResolver, which can be injected through the constructor or a setter.
For your production code, you would then create a new class that implements the IDirectoryResolver interface. This class could use the Directory.GetDirectories method in its implementation of the interface method.
For unit testing, you could create a MockDirectoryResolver class which implements IDirectoryResolver (or use a mocking library to create a mock instance for the interface). The mock implementation can do whatever you need it to do.
You would inject a wrapper class.
public class DirectoryFetcher
{
public virtual List<string> GetDirectoriesIn(string directory)
{
return Directory.GetDirectories(directory);
}
}
And then inject that:
foreach(string directory in _directoryFetcher.GetDirectoriesIn(server.Path))
{
// Whatever
}
You can then Mock that guy at the injection point (this example uses Moq, and constructor injection):
Mock<DirectoryFetcher> mockFetcher = new Mock<DirectoryFetcher>();
mockFetcher.Setup(x => x.GetDirectoriesIn("SomeDirectory")).Returns(new List<string>
{
"SampleDirectory1",
"SampleDirectory2"
});
MyObjectToTest testObj = new MyObjectToTest(mockFetcher.Object);
// Do Test
When communicating with the outside world, such as file system, databases, web services etc. , you should always consider using wrapper classes like the others before me suggested. Testability is one major argument, but an even bigger one is: The out side world changes, and you have no control over it. Folders move, user rights changes, new disk drives appears and old ones are removed. You only want to care about stuff like that in one place. Hence, the wrapper -- let's call it DirectoryResolver like Andy White suggested ealier.
So, wrap your file system calls, extract an interface, and inject that interface where you need to communicate with the file system.
The best solution I've found was to use Moles. The code is very specific, and must do very specific thing. Wrapping it with wrapper class will be redundant. The only reason I needed wrapper class is in order to write tests. Moles allows me to write the tests without any wrapper class :)