I'm trying to figure out how to correctly mock the #mailchimp/mailchimp_transactional npm module in my tests.
I'm getting caught up in how it shows to import mailchimp from the documentation, with an immediate call to the constructor with the API key
const mailchimp = require('#mailchimp/mailchimp_transactional')(API_KEY);
According to the Jest documentation, I'd normally mock it with something like
jest.mock('#mailchimp/mailchimp_transactional');
But I'm not sure how to then create the instance with a fake API key? I keep getting an undefined result from trying to call the mocked version of mailchimp. Would I need to mock a constructor() function as well?
I think it should be something like this:
jest.mock(
'#mailchimp/mailchimp_transactional',
() => API_KEY => ({ object that mocks mailchimp })
);
Related
I have a simple Observable piping from another Observable that I want to test.
const loginState$ = messageBusObservables.loginState$.pipe(
startWith({ isLoggedIn: false })
pluck('isLoggedIn'),
distinctUntilChanged()
)
messageBusObservables is an object of observables. Where loginState$ is an Observable.
In my tests, I thought I would easily be able to mock the './messageBus' module like this: (how the module is imported is irrelevant, but import preferred)
import { of } from 'rxjs'
import './messageBus'
jest.mock('./messageBus', () => ({
loginState$: of({ isLoggedIn: true }),
}))
However, Jest throws the error:
babel-plugin-jest-hoist: The module factory of jest.mock() is not allowed to reference any out-of-scope variables.
Invalid variable access: of
I have tried, putting it in a jest.fn() I have tried extracting of({ isLoggedIn: true }) to a variable. But I keep getting the same error from jest.
So how can I mock the input into my Observables using Jest? I'll run into the same problem with other observables using .merge, .zip etc.
It needs to be a real observable that is the input of my other observables. I just want to mock the value with something like of() rather than mocking an object, with a method on it, that returns an object with a .pipe method etc. (I don't want to mock the functionality of an Observable). I want to pass it a real observable with a value set in my unit test.
I also need these mocks to be dynamic. So the mock from 1 assertion can be different from the mock in the next assertion. (clearing them with something like a beforeEach)
EDIT:
I also tried to use babel-plugin-rewire to mock this module, this worked fine in the *.test.js file where I was mocking it. But in the actual file no matter what I set the export to using rewire, it always got imported as the original Observable.
the reason you are getting this message:
babel-plugin-jest-hoist: The module factory of jest.mock() is not allowed to reference any out-of-scope variables. Invalid variable access: of
is because jest automatically hoists calls to jest.mock so that they happen before the imports.
You have two options to get around this default behaviour, the simple way is to use jest.doMock which is NOT hoisted:
jest.doMock('./messageBus', () => ({
loginState$: of({ isLoggedIn: true }),
}))
Alternatively, you can prefix all the variables referenced inside the mock factory passed to jest.mock with "mock":
const mockMessageBus = {
loginState$: of({ isLoggedIn: true }),
}
jest.doMock('./messageBus', () => mockMessageBus)
(note that you are responsible for ensuring all mock variables referenced in the factory function are in scope when jest.mock is called)
You're close.
You are trying to mock the module by passing a module factory as the second parameter to jest.mock. The main constraint of that approach is that the module factory must be completely self-contained and "is not allowed to reference any out-of-scope variables".
Referencing of from rxjs in the module factory (as you have found) breaks that constraint and causes the error you are seeing.
Fortunately there are other ways to mock modules.
From what I can see of your code it looks like the easiest approach would be to create a Manual Mock of the messageBus module.
Create a __mocks__ folder in the same directory as messageBus.js and create the mock (also called messageBus.js) within the __mocks__ folder.
__mocks__/messageBus.js will look something like this:
import { of } from 'rxjs'
export default {
loginState$: of({ isLoggedIn: true })
}
Then tell Jest you want to use the manual mock within your test by calling
jest.mock('messageBus');
at the top of your test file.
That call is hoisted by Jest and ensures that any code that imports messageBus during the test will get the mocked module.
I am trying to mock a CakePHP 3 component which checks if the user is allowed to view the page or not.
I tried this:
$authComponent = $this->getMockBuilder(App\Controller\Component\AuthorizationComponent::class)
->getMock();
$authComponent
->method('isAuthorized')
->willReturn($this->returnValue(true));
However, when running the test, it says:
Trying to configure method "isAuthorized" which cannot be configured because it does not exist, has not been specified, is final, or is static
Most probably I wrongly created the mock. Can anyone tell me how to do it correctly?
Specify mocked methods with setMethods() before getMock():
$authComponent = $this
->getMockBuilder(App\Controller\Component\AuthorizationComponent::class)
->setMethods(['isAuthorized'])
->getMock();
Running ember 1.13.6 and ember-cli
I have an ember component which I am trying to acceptance test. It's state is very closely tied to the state of a service within my app and so I would like to directly access that service and change its properties from within my acceptance test.
I have been trying things along the lines of
this.application.__container__.lookup['service:side-bar'])
and
this.application.__container__.cache['service:side-bar'])
but I cannot seem to get the actual active service singleton which my app is using and which I could call get() and set() on.
if I try to use Ember.inject.service i get an obscure error Uncaught TypeError: Object.defineProperty called on non-object(…) which sort of sounds like a bug
I'm successfully getting at a service in 1.13.x by doing something like this:
let myService;
module("Acceptance | xxxxx", {
beforeEach() {
this.application = startApp()
myService = this.application.__container__.lookup('service:my-service');
}
});
Your problem might be that you're trying to use array notation (lookup['my-service']) rather than method invocation (lookup('my-service')).
Hope this helps!
We are implementing resource ownership and/or input validations through the use of FormRequest. Our controller tests are functional test so we don't mock Request but use the $this->call($method, $url, $params, ...).
The issue is that FormRequest is a subclass of Request. Is there a way to mock only the authorize() method but keeping the rest of the Request object non-mocked?
If so, how to? I already tried partial mocking with Mockery and it either didn't work or I did it wrong.
$this->mock(\Namespace\Http\Requests\CustomRequest::class . '[authorize]')
->shouldReceive('authorize')
-> .......
Use phpunit mocking system instead of Mockery.
$request = $this->getMock(\Namespace\http\Requests\CustomRequest::class, ['authorize']);
$request->expects($this->once())->method('authorize')->willReturn(true);
hope it helps;
Just begun creating some unit tests for my controllers within my CakePHP application however I am completely flummoxed on how I should create a mock for the Auth Component, I have read the CookBook and thought I had it right, but keep getting thrown this error.
Error: Call to a member function allow() on a non-object
Within the controller I am testing there is a beforeFilter function with the following code:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('create');
}
Within my test I have included the following:
$Leagues = $this->generate('Leagues', array(
'components' => array(
'Auth'
)
));
I have played around with staticExpects() also but it doesn't seem to have much affect (I am also unsure what I need to put in to staticExpects()).
What do you mean by mock? Just stuffing an object with data that you set? The error you're getting is because you need to use
$this->Auth->allow(array('create'))
Found the issue - I have included the Auth component within AppController.php, and not specifically within the controller I was trying to test. By including it with my controller specifically the errors have gone away.