question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Instance matcher and mocks confusion

See original GitHub issue

Hi, we just tried to move to your library from chai. But we were unable to find a matcher for instances. Is there any such matcher yet? How would I write the following chai expect in earl?

const service = new Service();
chai.expect(service).to.be.instanceOf(Service);

Same applies for the property matcher. Sometimes we want to check if an object has a property.

chai.expect(service).to.have.property("prop");

Of course we can circumvent both with equal like

const service = new Service();
chai.expect(service instanceof Service).toEqual(true);
chai.expect(Object.prototype.hasOwnProperty.call(service, "prop")).toEqual(true);

but the method chai offers seems a little bit easier in my opinion.

Also a Regex matcher would be very nice to have. Currently I have to do something like this:

expect(new RegExp(/Error while starting the server.*/).test(msg)).toEqual(true);

which works but the error message is very unspecific being only Error: false not equal to true.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
Kampfmoehrecommented, May 27, 2020

No problem. Your library is awesome so far. Testing with typescript always felt a little bit strange. Mocha is difficult when you have multiple different test suites that need different setups (we split our tests in unit, api and integration) and jest always feels way to slow with typescript. We also checked out alsatian but it wont work with the many reporters we need.

The biggest obstacle I had with Typescript are mocks. They almost never are typed and/or easy to use at the same time and I am far from understanding how to type them properly with sinon or jest. The best thing that I have found so far is typemoq which is inspired by C# and thus I am familiar with it. But in the TS/JS world it seems a little bit too much code for mocking. But it creates correctly typed mocks to use and I don’t have to mock everything but only the parts I need.

As far as I have tested your library, I am unsure if and how we use your mocking functionality. In the example above I would need to provide a logger. Most of our code is written with dependency injection so it should be easy to just provide fake instances in tests, right? But often Typescript is making things hard here.

This is how many of our services are written:

export class Service {
  private readonly logger: LoggerBase;

  constructor(loggerFactory: (name: string|Function) => LoggerBase) {
    this.logger = loggerFactory(this.constructor);
}

Now LoggerBase is defined as an interface that has logger function like info, warn, error and so on which each take an object, a string and template params (for the string). Now since it doesn’t create it’s own logger, it should be easy to just provide a fake one when instantiating from our test, shouldn’t it? Well since all those methods are defined in LoggerBase, typescript wants to have them all, when we create a fake logger:

new Service(() => ({info: ()=> {}}));
// Typescript throws an error like `Type '{ info: () => void; }' is missing the following properties from type 'LoggerBase': trace, debug, warn, error, fatal`

But I only need info for my test. Nearly every mocking framework I tried so far does not handle this very well. I always have to work with casts and loose types or have to silence eslint and typescript. Since most of them are written for JS I guess they don’t care much.

What I am really looking for is something like typemoq provides:

const mock = Mock.of(LoggerBase); // Difficult because LoggerBase is only an interface here so it would be an empty object at runtime
mock.setup("info").withArgs("arg1", AnyString(), ...).return("Whatever"); // ... makes no sense for logger to return something but you'll get the point)

new Service(() => mock.object) // this should have the correct type so ts won't complain and no casts are needed

expect(mock.info).toHaveBeenCalledWith("arg1", "arg2", "...");
// or
mock.verify(); // Throws if not called with the correct arguments

0reactions
krzkaczorcommented, Nov 14, 2020

Mocks were redesigned now. Head to https://earljs.dev/docs/guides/mocks for the new docs.

Read more comments on GitHub >

github_iconTop Results From Across the Web

What's the difference between Mockito Matchers isA, any, eq ...
any() checks absolutely nothing. Since Mockito 2.0, any(T.class) shares isA semantics to mean "any T " or properly "any instance of type T...
Read more >
instance_double not matching the same class it is mocking #794
I have a test case wherin an instance_double of a class does not think it is a kind_of / is_a / === of...
Read more >
Any Instance - Working with legacy code - RSpec Mocks - Relish
As a result there are some semantically confusing edge cases. For example, in expect_any_instance_of(Widget).to receive(:name).twice it isn't clear whether a ...
Read more >
How to Improve Ruby Tests Using RSpec Mocks - Netguru
The goal of this article is to provide a succinct summary of mocking techniques in RSpec tests along with code examples presenting typical ......
Read more >
ArgumentMatcher (Mockito 2.0.66-beta API) - Javadoc.io
implement equals() method in the objects that are used as arguments to mocks. Mockito naturally uses equals() for argument matching. Many times, this...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found