0

I am looking for asserting that a statement is covered in my test. For instance, let's say from test am calling methodA() which has reference to methodB().

I would like to assert that methodB() is called upon executing methodA() from tests.

In the following code how do I assert in A Go test that svc.AddCheck() is called on execution of svc.OnStartup()?

func (svc *Servjice) OnStartup() error {
    if err := svc.AddCheck("cache"); err != nil {
        return err
    }
    return nil
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Mozhi
  • 757
  • 1
  • 11
  • 28
  • 1
    In Go you can't mock concrete methods, only interface methods and function values, e.g. a function field or variable. – mkopriva Sep 03 '19 at 06:53
  • Note that Go has no classes. Your question (which I edited for spelling) referred to a "Go test class". This doesn't exist. Get it out of your head that Go has classes or anything like classes. – Jonathan Hall Sep 03 '19 at 08:14
  • 1
    Usually, trying to assert that a specific method was called, is _bad practice_ in _any language_. You should be testing that the method does what you expect--not _how_ it does it. Testing that it calls a specific method is a "how" test not a "what" test. – Jonathan Hall Sep 03 '19 at 08:15
  • 1
    @PanagiotisKanavos: Struct vs class isn't just semantics. It's a _fundamentally different way of thinking_. People who think about Classes are constantly confused by Go for this very reason. If you think a struct "is basically a class", that **IS** wrong. It doesn't make the developer a bad person. It just means they have a mistaken concept. The point of such comments is to correct them, not criticize. Don't take things so personally. – Jonathan Hall Sep 03 '19 at 09:25
  • @Flimzy I didn't say it is. And I remember saying that there's no need for class inheritance, just interfaces back in the VB6 days. Now, if you find that link amusing, check the vote count. You have enough rep to see the 5 downvotes. I bet those 141 upvotes came after the article was published. It's actually *very* common to find mass downvotes in new questions in the `go` tag, almost 1 or 2 per week – Panagiotis Kanavos Sep 03 '19 at 09:31
  • 1
    On a different note, I might add that there is a very good reason that you can only mock interfaces. It _forces_ you to develop against interfaces, which should be done for obvious reasons. – Markus W Mahlberg Sep 03 '19 at 09:58

2 Answers2

3

Is it possible to assert that a real method is called via spying in Go like Java Mockito?

In a word: No.

But what about alternatives?

What you should be testing for is the effects of your function. This is true in any language, not just Go. This is also true whether you're doing unit testing or some higher-level type of testing, including end-to-end testing.

If your methodB() calls methodA(), it's not useful to check, per se, that methodA() is called. What is useful is to check that methodB() does what you expect. Whether it uses methodA() to accomplish that or not, is an implementation detail that your test, by definition, should not care about.

Some examples:

  • Suppose you're writing an integration test, and methodA() inserts something into the database. Don't assert that methodA() is called--instead assert that the row you expect is now in the database.

  • Suppose you're writing a unit test for a Fibonacci generator. Don't assert whether it calls methodA(), assert whether it returns the correct value.

When you assert that a sub-method is called, you're worried about implementation details--the "how" of your function. That's not what good tests do. Good tests assure that your method produces the correct result. It shouldn't matter, from a testing standpoint, whether it does that by calling methodA(), methodZ(), a REST API, or using Jedi powers.

So TL;DR; No, you can't do what you're asking, but that's okay because you shouldn't do what you're asking. There are better alternatives (even in Java).

Peter
  • 29,454
  • 5
  • 48
  • 60
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
  • Thank you for your insights , I agree with you but what should i do with external dependencies in the code , for instance ~ In my method i have some database interactions , to write unit tests i have to mock those interactions but i don't want any other developer to accidentally delete those lines that does affect the functionality. I think the case of external dependencies does required to mock and assert that they are called . Hope you will agree with me... – Mozhi Sep 03 '19 at 15:45
2

Is it possible to assert that a real method is called via spying in golang like Java Mockito?

No, not at all.

Volker
  • 40,468
  • 7
  • 81
  • 87