How to unit test methods which using static methods?Static methods or static functions?How do you unit test private methods?Interfacing application code with unit testsCorrect Seam for StubReal time unit testing - or “how to mock now”How to unit test static void methods?Using static methods in layered architectureStatic methods and testabilityIs it good practice to stub an object not because it is slow, but to prevent testing it twice?Which code to unit-test?
How is this practical and very old scene shot?
Why is Japan trying to have a better relationship with Iran?
Company threatening to call my current job after I declined their offer
How to plan the font size in a fiction?
Journal standards vs. personal standards
What is this mount with two buttons on side of Vivitar 75-205mm lens?
Are all commands with an optional argument fragile?
Sacrifice blocking creature before damage is dealt no longer working (MtG Arena)?
Is there reliable evidence that depleted uranium from the 1999 NATO bombing is causing cancer in Serbia?
13th chords on guitar
What is "oversubscription" in Networking?
What will happen if I checked in for another room in the same hotel, but not for the booked one?
How can a valley surrounded by mountains be fertile and rainy?
What exactly did Ant-Man see that made him say that their plan worked?
How to properly say asset/assets in German
What do you call a notepad used to keep a record?
How do I ensure my employees don't abuse my flexible work hours policy?
Bin Packing with Relational Penalization
If two black hole event horizons overlap (touch) can they ever separate again?
Are gliders susceptible to bird strikes?
What verb for taking advantage fits in "I don't want to ________ on the friendship"?
Comment traduire « That screams X »
Most important new papers in computational complexity
Warnings of R. Chaim Vital
How to unit test methods which using static methods?
Static methods or static functions?How do you unit test private methods?Interfacing application code with unit testsCorrect Seam for StubReal time unit testing - or “how to mock now”How to unit test static void methods?Using static methods in layered architectureStatic methods and testabilityIs it good practice to stub an object not because it is slow, but to prevent testing it twice?Which code to unit-test?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
Let's assume I wrote an extension method in c# for byte
arrays which encodes them into hex strings, as follows:
public static class Extensions
public static string ToHex(this byte[] binary)
const string chars = "0123456789abcdef";
var resultBuilder = new StringBuilder();
foreach(var b in binary)
resultBuilder.Append(chars[(b >> 4) & 0xf]).Append(chars[b & 0xf]);
return resultBuilder.ToString();
I could test the method above using nunit as follows:
[Test]
public void TestToHex_Works()
var bytes = new byte[] 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef ;
Assert.AreEqual("0123456789abcdef", bytes.ToHex());
If I use the Extensions.ToHex
inside my project, let's assume in Foo.Do
method as follows:
public class Foo
public bool Do(byte[] payload)
var data = "ES=" + payload.ToHex() + "ff";
// ...
return data.Length > 5;
// ...
Then all tests of Foo.Do
will depend on the success of TestToHex_Works
.
Using free functions in c++ the outcome will be the same: tests that test methods that use free functions will depend on the success of free function tests.
How can I handle such situations? Can I somehow resolve these test dependencies? Is there a better way to test the code snippets above?
unit-testing static-methods
add a comment |
Let's assume I wrote an extension method in c# for byte
arrays which encodes them into hex strings, as follows:
public static class Extensions
public static string ToHex(this byte[] binary)
const string chars = "0123456789abcdef";
var resultBuilder = new StringBuilder();
foreach(var b in binary)
resultBuilder.Append(chars[(b >> 4) & 0xf]).Append(chars[b & 0xf]);
return resultBuilder.ToString();
I could test the method above using nunit as follows:
[Test]
public void TestToHex_Works()
var bytes = new byte[] 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef ;
Assert.AreEqual("0123456789abcdef", bytes.ToHex());
If I use the Extensions.ToHex
inside my project, let's assume in Foo.Do
method as follows:
public class Foo
public bool Do(byte[] payload)
var data = "ES=" + payload.ToHex() + "ff";
// ...
return data.Length > 5;
// ...
Then all tests of Foo.Do
will depend on the success of TestToHex_Works
.
Using free functions in c++ the outcome will be the same: tests that test methods that use free functions will depend on the success of free function tests.
How can I handle such situations? Can I somehow resolve these test dependencies? Is there a better way to test the code snippets above?
unit-testing static-methods
3
Then all tests of Foo.Do will depend on the success of TestToHex_works
-- So? You don't have classes that depend on the success of other classes?
– Robert Harvey♦
9 hours ago
2
I've never quite understood this obsession with free/static functions and their so-called non-testability. If a free function is free of side-effects, it is the easiest thing on the planet to test and prove it works. You've demonstrated this quite effectively in your own question. How do you test ordinary, side-effect free methods (that aren't dependent on class state) in object instances? I know you have some of those.
– Robert Harvey♦
9 hours ago
The only downside of this code using static functions is that you can’t easily use something else thantoHex
(or swap implementations). Apart from that everything is fine. Your code converting to hex is tested, now there’s another code using that tested code as a utility to achieve its own goal.
– Steve Chamaillard
8 hours ago
2
I am completely missing what is the problem here. If ToHex doesn't work, then it's clear that Do won't work either.
– Simon B
8 hours ago
2
The test for Foo.Do() shouldn't know or care that it calls ToHex() under the covers, that's an implementation detail.
– 17 of 26
7 hours ago
add a comment |
Let's assume I wrote an extension method in c# for byte
arrays which encodes them into hex strings, as follows:
public static class Extensions
public static string ToHex(this byte[] binary)
const string chars = "0123456789abcdef";
var resultBuilder = new StringBuilder();
foreach(var b in binary)
resultBuilder.Append(chars[(b >> 4) & 0xf]).Append(chars[b & 0xf]);
return resultBuilder.ToString();
I could test the method above using nunit as follows:
[Test]
public void TestToHex_Works()
var bytes = new byte[] 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef ;
Assert.AreEqual("0123456789abcdef", bytes.ToHex());
If I use the Extensions.ToHex
inside my project, let's assume in Foo.Do
method as follows:
public class Foo
public bool Do(byte[] payload)
var data = "ES=" + payload.ToHex() + "ff";
// ...
return data.Length > 5;
// ...
Then all tests of Foo.Do
will depend on the success of TestToHex_Works
.
Using free functions in c++ the outcome will be the same: tests that test methods that use free functions will depend on the success of free function tests.
How can I handle such situations? Can I somehow resolve these test dependencies? Is there a better way to test the code snippets above?
unit-testing static-methods
Let's assume I wrote an extension method in c# for byte
arrays which encodes them into hex strings, as follows:
public static class Extensions
public static string ToHex(this byte[] binary)
const string chars = "0123456789abcdef";
var resultBuilder = new StringBuilder();
foreach(var b in binary)
resultBuilder.Append(chars[(b >> 4) & 0xf]).Append(chars[b & 0xf]);
return resultBuilder.ToString();
I could test the method above using nunit as follows:
[Test]
public void TestToHex_Works()
var bytes = new byte[] 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef ;
Assert.AreEqual("0123456789abcdef", bytes.ToHex());
If I use the Extensions.ToHex
inside my project, let's assume in Foo.Do
method as follows:
public class Foo
public bool Do(byte[] payload)
var data = "ES=" + payload.ToHex() + "ff";
// ...
return data.Length > 5;
// ...
Then all tests of Foo.Do
will depend on the success of TestToHex_Works
.
Using free functions in c++ the outcome will be the same: tests that test methods that use free functions will depend on the success of free function tests.
How can I handle such situations? Can I somehow resolve these test dependencies? Is there a better way to test the code snippets above?
unit-testing static-methods
unit-testing static-methods
asked 9 hours ago
AkiraAkira
1341 gold badge1 silver badge6 bronze badges
1341 gold badge1 silver badge6 bronze badges
3
Then all tests of Foo.Do will depend on the success of TestToHex_works
-- So? You don't have classes that depend on the success of other classes?
– Robert Harvey♦
9 hours ago
2
I've never quite understood this obsession with free/static functions and their so-called non-testability. If a free function is free of side-effects, it is the easiest thing on the planet to test and prove it works. You've demonstrated this quite effectively in your own question. How do you test ordinary, side-effect free methods (that aren't dependent on class state) in object instances? I know you have some of those.
– Robert Harvey♦
9 hours ago
The only downside of this code using static functions is that you can’t easily use something else thantoHex
(or swap implementations). Apart from that everything is fine. Your code converting to hex is tested, now there’s another code using that tested code as a utility to achieve its own goal.
– Steve Chamaillard
8 hours ago
2
I am completely missing what is the problem here. If ToHex doesn't work, then it's clear that Do won't work either.
– Simon B
8 hours ago
2
The test for Foo.Do() shouldn't know or care that it calls ToHex() under the covers, that's an implementation detail.
– 17 of 26
7 hours ago
add a comment |
3
Then all tests of Foo.Do will depend on the success of TestToHex_works
-- So? You don't have classes that depend on the success of other classes?
– Robert Harvey♦
9 hours ago
2
I've never quite understood this obsession with free/static functions and their so-called non-testability. If a free function is free of side-effects, it is the easiest thing on the planet to test and prove it works. You've demonstrated this quite effectively in your own question. How do you test ordinary, side-effect free methods (that aren't dependent on class state) in object instances? I know you have some of those.
– Robert Harvey♦
9 hours ago
The only downside of this code using static functions is that you can’t easily use something else thantoHex
(or swap implementations). Apart from that everything is fine. Your code converting to hex is tested, now there’s another code using that tested code as a utility to achieve its own goal.
– Steve Chamaillard
8 hours ago
2
I am completely missing what is the problem here. If ToHex doesn't work, then it's clear that Do won't work either.
– Simon B
8 hours ago
2
The test for Foo.Do() shouldn't know or care that it calls ToHex() under the covers, that's an implementation detail.
– 17 of 26
7 hours ago
3
3
Then all tests of Foo.Do will depend on the success of TestToHex_works
-- So? You don't have classes that depend on the success of other classes?– Robert Harvey♦
9 hours ago
Then all tests of Foo.Do will depend on the success of TestToHex_works
-- So? You don't have classes that depend on the success of other classes?– Robert Harvey♦
9 hours ago
2
2
I've never quite understood this obsession with free/static functions and their so-called non-testability. If a free function is free of side-effects, it is the easiest thing on the planet to test and prove it works. You've demonstrated this quite effectively in your own question. How do you test ordinary, side-effect free methods (that aren't dependent on class state) in object instances? I know you have some of those.
– Robert Harvey♦
9 hours ago
I've never quite understood this obsession with free/static functions and their so-called non-testability. If a free function is free of side-effects, it is the easiest thing on the planet to test and prove it works. You've demonstrated this quite effectively in your own question. How do you test ordinary, side-effect free methods (that aren't dependent on class state) in object instances? I know you have some of those.
– Robert Harvey♦
9 hours ago
The only downside of this code using static functions is that you can’t easily use something else than
toHex
(or swap implementations). Apart from that everything is fine. Your code converting to hex is tested, now there’s another code using that tested code as a utility to achieve its own goal.– Steve Chamaillard
8 hours ago
The only downside of this code using static functions is that you can’t easily use something else than
toHex
(or swap implementations). Apart from that everything is fine. Your code converting to hex is tested, now there’s another code using that tested code as a utility to achieve its own goal.– Steve Chamaillard
8 hours ago
2
2
I am completely missing what is the problem here. If ToHex doesn't work, then it's clear that Do won't work either.
– Simon B
8 hours ago
I am completely missing what is the problem here. If ToHex doesn't work, then it's clear that Do won't work either.
– Simon B
8 hours ago
2
2
The test for Foo.Do() shouldn't know or care that it calls ToHex() under the covers, that's an implementation detail.
– 17 of 26
7 hours ago
The test for Foo.Do() shouldn't know or care that it calls ToHex() under the covers, that's an implementation detail.
– 17 of 26
7 hours ago
add a comment |
2 Answers
2
active
oldest
votes
Then all tests of
Foo.Do
will depend on the success ofTestToHex
_Works.
Yes. That's why you have tests for TextToHex
. If those tests pass, the function meets the spec defined in those tests. So Foo.Do
can safely call it and not worry about it. It's covered already.
You could add an interface, make the method an instance method and inject it into Foo
. Then you could mock TextToHex
. But now you have to write a mock, which may function differently. So you'll need an "integration" test to bring the two together to ensure the parts really work together. What has that achieved other than making things more complex?
The idea that unit tests should test parts of your code in isolation from other parts is a fallacy. The "unit" in a unit test is an isolated unit of execution. If two tests can be run simultaneously without affecting each other, then they run in isolation and so are unit tests. Static functions that are fast, do not have a complex set up and have no side effects such as your example are therefore fine to use directly in unit tests. If you have code that is slow, complex to set up or has side effects, then mocks are useful. They should be avoided elsewhere though.
You make a pretty good argument for "test-first" development. Mocking exists in part because code gets written in such a way that it is too hard to test, and if you write your tests first, you force yourself to write code that is more easily testable.
– Robert Harvey♦
7 hours ago
add a comment |
Exactly. And this is one of the problems with static methods, another one being that OOP is a much better alternative in most situations.
This is also one of the reasons Dependency Injection is used.
In your case, you may prefer having a concrete converter that you inject into a class which needs a conversion of some values to hexadecimal. An interface, implemented by this concrete class, would define the contract required to convert the values.
Not only would you be able to test your code easier, but you'll also be able to swap implementations later (since there are lots of other possible ways of converting values to hexadecimal, some of them producing different outputs).
1
How will that not make the code dependant on the success of the converter tests ? Injecting a class, an interface or anything you want does not make it magically work. If you were talking about side effects then yes there would be a ton of value injecting a fake instead of hard coding an implementation, but that problem never existed in the first place anyway.
– Steve Chamaillard
8 hours ago
@steve when a unit fails do you want to see a sea of red in your test results, or just have the broken code show red?
– Ewan
7 hours ago
1
@ArseniMourzenko so when injecting a calculator class implementing amultiply
method, you'd mock this? Which means in order to refactor (and use the * operator instead), you'll have to change every single mock declaration in your code? Doesn't look like easy code to me. All I'm saying istoHex
is very simple and has no side effects at all so I don't see any reason to mock or stub this. It's too much cost for absolutely no profit. Not saying we shouldn't inject it though, but that depends on usage.
– Steve Chamaillard
7 hours ago
1
@steve surely this is exactly what arseni is saying. The static call is bad design, you want your unit tests to test specific parts of the code and static prevents this. Saying 'its a simple function that will never break' doesnt help you when it does break
– Ewan
7 hours ago
1
@ArseniMourzenko I wasn't clear, I don't think having an interface is complex at all in this situation. I was saying that using mocks in these situations seem overkill and make tests harder to read, to write and to modify. When I say "doesn't look like easy code", I'm extrapolating to the case wheretoHex
is used everywhere and so if tested with mocking every time well for any change I'll have to change many tests, right?
– Steve Chamaillard
6 hours ago
|
show 9 more comments
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "131"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f393870%2fhow-to-unit-test-methods-which-using-static-methods%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Then all tests of
Foo.Do
will depend on the success ofTestToHex
_Works.
Yes. That's why you have tests for TextToHex
. If those tests pass, the function meets the spec defined in those tests. So Foo.Do
can safely call it and not worry about it. It's covered already.
You could add an interface, make the method an instance method and inject it into Foo
. Then you could mock TextToHex
. But now you have to write a mock, which may function differently. So you'll need an "integration" test to bring the two together to ensure the parts really work together. What has that achieved other than making things more complex?
The idea that unit tests should test parts of your code in isolation from other parts is a fallacy. The "unit" in a unit test is an isolated unit of execution. If two tests can be run simultaneously without affecting each other, then they run in isolation and so are unit tests. Static functions that are fast, do not have a complex set up and have no side effects such as your example are therefore fine to use directly in unit tests. If you have code that is slow, complex to set up or has side effects, then mocks are useful. They should be avoided elsewhere though.
You make a pretty good argument for "test-first" development. Mocking exists in part because code gets written in such a way that it is too hard to test, and if you write your tests first, you force yourself to write code that is more easily testable.
– Robert Harvey♦
7 hours ago
add a comment |
Then all tests of
Foo.Do
will depend on the success ofTestToHex
_Works.
Yes. That's why you have tests for TextToHex
. If those tests pass, the function meets the spec defined in those tests. So Foo.Do
can safely call it and not worry about it. It's covered already.
You could add an interface, make the method an instance method and inject it into Foo
. Then you could mock TextToHex
. But now you have to write a mock, which may function differently. So you'll need an "integration" test to bring the two together to ensure the parts really work together. What has that achieved other than making things more complex?
The idea that unit tests should test parts of your code in isolation from other parts is a fallacy. The "unit" in a unit test is an isolated unit of execution. If two tests can be run simultaneously without affecting each other, then they run in isolation and so are unit tests. Static functions that are fast, do not have a complex set up and have no side effects such as your example are therefore fine to use directly in unit tests. If you have code that is slow, complex to set up or has side effects, then mocks are useful. They should be avoided elsewhere though.
You make a pretty good argument for "test-first" development. Mocking exists in part because code gets written in such a way that it is too hard to test, and if you write your tests first, you force yourself to write code that is more easily testable.
– Robert Harvey♦
7 hours ago
add a comment |
Then all tests of
Foo.Do
will depend on the success ofTestToHex
_Works.
Yes. That's why you have tests for TextToHex
. If those tests pass, the function meets the spec defined in those tests. So Foo.Do
can safely call it and not worry about it. It's covered already.
You could add an interface, make the method an instance method and inject it into Foo
. Then you could mock TextToHex
. But now you have to write a mock, which may function differently. So you'll need an "integration" test to bring the two together to ensure the parts really work together. What has that achieved other than making things more complex?
The idea that unit tests should test parts of your code in isolation from other parts is a fallacy. The "unit" in a unit test is an isolated unit of execution. If two tests can be run simultaneously without affecting each other, then they run in isolation and so are unit tests. Static functions that are fast, do not have a complex set up and have no side effects such as your example are therefore fine to use directly in unit tests. If you have code that is slow, complex to set up or has side effects, then mocks are useful. They should be avoided elsewhere though.
Then all tests of
Foo.Do
will depend on the success ofTestToHex
_Works.
Yes. That's why you have tests for TextToHex
. If those tests pass, the function meets the spec defined in those tests. So Foo.Do
can safely call it and not worry about it. It's covered already.
You could add an interface, make the method an instance method and inject it into Foo
. Then you could mock TextToHex
. But now you have to write a mock, which may function differently. So you'll need an "integration" test to bring the two together to ensure the parts really work together. What has that achieved other than making things more complex?
The idea that unit tests should test parts of your code in isolation from other parts is a fallacy. The "unit" in a unit test is an isolated unit of execution. If two tests can be run simultaneously without affecting each other, then they run in isolation and so are unit tests. Static functions that are fast, do not have a complex set up and have no side effects such as your example are therefore fine to use directly in unit tests. If you have code that is slow, complex to set up or has side effects, then mocks are useful. They should be avoided elsewhere though.
answered 8 hours ago
David ArnoDavid Arno
30.4k7 gold badges63 silver badges98 bronze badges
30.4k7 gold badges63 silver badges98 bronze badges
You make a pretty good argument for "test-first" development. Mocking exists in part because code gets written in such a way that it is too hard to test, and if you write your tests first, you force yourself to write code that is more easily testable.
– Robert Harvey♦
7 hours ago
add a comment |
You make a pretty good argument for "test-first" development. Mocking exists in part because code gets written in such a way that it is too hard to test, and if you write your tests first, you force yourself to write code that is more easily testable.
– Robert Harvey♦
7 hours ago
You make a pretty good argument for "test-first" development. Mocking exists in part because code gets written in such a way that it is too hard to test, and if you write your tests first, you force yourself to write code that is more easily testable.
– Robert Harvey♦
7 hours ago
You make a pretty good argument for "test-first" development. Mocking exists in part because code gets written in such a way that it is too hard to test, and if you write your tests first, you force yourself to write code that is more easily testable.
– Robert Harvey♦
7 hours ago
add a comment |
Exactly. And this is one of the problems with static methods, another one being that OOP is a much better alternative in most situations.
This is also one of the reasons Dependency Injection is used.
In your case, you may prefer having a concrete converter that you inject into a class which needs a conversion of some values to hexadecimal. An interface, implemented by this concrete class, would define the contract required to convert the values.
Not only would you be able to test your code easier, but you'll also be able to swap implementations later (since there are lots of other possible ways of converting values to hexadecimal, some of them producing different outputs).
1
How will that not make the code dependant on the success of the converter tests ? Injecting a class, an interface or anything you want does not make it magically work. If you were talking about side effects then yes there would be a ton of value injecting a fake instead of hard coding an implementation, but that problem never existed in the first place anyway.
– Steve Chamaillard
8 hours ago
@steve when a unit fails do you want to see a sea of red in your test results, or just have the broken code show red?
– Ewan
7 hours ago
1
@ArseniMourzenko so when injecting a calculator class implementing amultiply
method, you'd mock this? Which means in order to refactor (and use the * operator instead), you'll have to change every single mock declaration in your code? Doesn't look like easy code to me. All I'm saying istoHex
is very simple and has no side effects at all so I don't see any reason to mock or stub this. It's too much cost for absolutely no profit. Not saying we shouldn't inject it though, but that depends on usage.
– Steve Chamaillard
7 hours ago
1
@steve surely this is exactly what arseni is saying. The static call is bad design, you want your unit tests to test specific parts of the code and static prevents this. Saying 'its a simple function that will never break' doesnt help you when it does break
– Ewan
7 hours ago
1
@ArseniMourzenko I wasn't clear, I don't think having an interface is complex at all in this situation. I was saying that using mocks in these situations seem overkill and make tests harder to read, to write and to modify. When I say "doesn't look like easy code", I'm extrapolating to the case wheretoHex
is used everywhere and so if tested with mocking every time well for any change I'll have to change many tests, right?
– Steve Chamaillard
6 hours ago
|
show 9 more comments
Exactly. And this is one of the problems with static methods, another one being that OOP is a much better alternative in most situations.
This is also one of the reasons Dependency Injection is used.
In your case, you may prefer having a concrete converter that you inject into a class which needs a conversion of some values to hexadecimal. An interface, implemented by this concrete class, would define the contract required to convert the values.
Not only would you be able to test your code easier, but you'll also be able to swap implementations later (since there are lots of other possible ways of converting values to hexadecimal, some of them producing different outputs).
1
How will that not make the code dependant on the success of the converter tests ? Injecting a class, an interface or anything you want does not make it magically work. If you were talking about side effects then yes there would be a ton of value injecting a fake instead of hard coding an implementation, but that problem never existed in the first place anyway.
– Steve Chamaillard
8 hours ago
@steve when a unit fails do you want to see a sea of red in your test results, or just have the broken code show red?
– Ewan
7 hours ago
1
@ArseniMourzenko so when injecting a calculator class implementing amultiply
method, you'd mock this? Which means in order to refactor (and use the * operator instead), you'll have to change every single mock declaration in your code? Doesn't look like easy code to me. All I'm saying istoHex
is very simple and has no side effects at all so I don't see any reason to mock or stub this. It's too much cost for absolutely no profit. Not saying we shouldn't inject it though, but that depends on usage.
– Steve Chamaillard
7 hours ago
1
@steve surely this is exactly what arseni is saying. The static call is bad design, you want your unit tests to test specific parts of the code and static prevents this. Saying 'its a simple function that will never break' doesnt help you when it does break
– Ewan
7 hours ago
1
@ArseniMourzenko I wasn't clear, I don't think having an interface is complex at all in this situation. I was saying that using mocks in these situations seem overkill and make tests harder to read, to write and to modify. When I say "doesn't look like easy code", I'm extrapolating to the case wheretoHex
is used everywhere and so if tested with mocking every time well for any change I'll have to change many tests, right?
– Steve Chamaillard
6 hours ago
|
show 9 more comments
Exactly. And this is one of the problems with static methods, another one being that OOP is a much better alternative in most situations.
This is also one of the reasons Dependency Injection is used.
In your case, you may prefer having a concrete converter that you inject into a class which needs a conversion of some values to hexadecimal. An interface, implemented by this concrete class, would define the contract required to convert the values.
Not only would you be able to test your code easier, but you'll also be able to swap implementations later (since there are lots of other possible ways of converting values to hexadecimal, some of them producing different outputs).
Exactly. And this is one of the problems with static methods, another one being that OOP is a much better alternative in most situations.
This is also one of the reasons Dependency Injection is used.
In your case, you may prefer having a concrete converter that you inject into a class which needs a conversion of some values to hexadecimal. An interface, implemented by this concrete class, would define the contract required to convert the values.
Not only would you be able to test your code easier, but you'll also be able to swap implementations later (since there are lots of other possible ways of converting values to hexadecimal, some of them producing different outputs).
answered 9 hours ago
Arseni MourzenkoArseni Mourzenko
116k26 gold badges293 silver badges462 bronze badges
116k26 gold badges293 silver badges462 bronze badges
1
How will that not make the code dependant on the success of the converter tests ? Injecting a class, an interface or anything you want does not make it magically work. If you were talking about side effects then yes there would be a ton of value injecting a fake instead of hard coding an implementation, but that problem never existed in the first place anyway.
– Steve Chamaillard
8 hours ago
@steve when a unit fails do you want to see a sea of red in your test results, or just have the broken code show red?
– Ewan
7 hours ago
1
@ArseniMourzenko so when injecting a calculator class implementing amultiply
method, you'd mock this? Which means in order to refactor (and use the * operator instead), you'll have to change every single mock declaration in your code? Doesn't look like easy code to me. All I'm saying istoHex
is very simple and has no side effects at all so I don't see any reason to mock or stub this. It's too much cost for absolutely no profit. Not saying we shouldn't inject it though, but that depends on usage.
– Steve Chamaillard
7 hours ago
1
@steve surely this is exactly what arseni is saying. The static call is bad design, you want your unit tests to test specific parts of the code and static prevents this. Saying 'its a simple function that will never break' doesnt help you when it does break
– Ewan
7 hours ago
1
@ArseniMourzenko I wasn't clear, I don't think having an interface is complex at all in this situation. I was saying that using mocks in these situations seem overkill and make tests harder to read, to write and to modify. When I say "doesn't look like easy code", I'm extrapolating to the case wheretoHex
is used everywhere and so if tested with mocking every time well for any change I'll have to change many tests, right?
– Steve Chamaillard
6 hours ago
|
show 9 more comments
1
How will that not make the code dependant on the success of the converter tests ? Injecting a class, an interface or anything you want does not make it magically work. If you were talking about side effects then yes there would be a ton of value injecting a fake instead of hard coding an implementation, but that problem never existed in the first place anyway.
– Steve Chamaillard
8 hours ago
@steve when a unit fails do you want to see a sea of red in your test results, or just have the broken code show red?
– Ewan
7 hours ago
1
@ArseniMourzenko so when injecting a calculator class implementing amultiply
method, you'd mock this? Which means in order to refactor (and use the * operator instead), you'll have to change every single mock declaration in your code? Doesn't look like easy code to me. All I'm saying istoHex
is very simple and has no side effects at all so I don't see any reason to mock or stub this. It's too much cost for absolutely no profit. Not saying we shouldn't inject it though, but that depends on usage.
– Steve Chamaillard
7 hours ago
1
@steve surely this is exactly what arseni is saying. The static call is bad design, you want your unit tests to test specific parts of the code and static prevents this. Saying 'its a simple function that will never break' doesnt help you when it does break
– Ewan
7 hours ago
1
@ArseniMourzenko I wasn't clear, I don't think having an interface is complex at all in this situation. I was saying that using mocks in these situations seem overkill and make tests harder to read, to write and to modify. When I say "doesn't look like easy code", I'm extrapolating to the case wheretoHex
is used everywhere and so if tested with mocking every time well for any change I'll have to change many tests, right?
– Steve Chamaillard
6 hours ago
1
1
How will that not make the code dependant on the success of the converter tests ? Injecting a class, an interface or anything you want does not make it magically work. If you were talking about side effects then yes there would be a ton of value injecting a fake instead of hard coding an implementation, but that problem never existed in the first place anyway.
– Steve Chamaillard
8 hours ago
How will that not make the code dependant on the success of the converter tests ? Injecting a class, an interface or anything you want does not make it magically work. If you were talking about side effects then yes there would be a ton of value injecting a fake instead of hard coding an implementation, but that problem never existed in the first place anyway.
– Steve Chamaillard
8 hours ago
@steve when a unit fails do you want to see a sea of red in your test results, or just have the broken code show red?
– Ewan
7 hours ago
@steve when a unit fails do you want to see a sea of red in your test results, or just have the broken code show red?
– Ewan
7 hours ago
1
1
@ArseniMourzenko so when injecting a calculator class implementing a
multiply
method, you'd mock this? Which means in order to refactor (and use the * operator instead), you'll have to change every single mock declaration in your code? Doesn't look like easy code to me. All I'm saying is toHex
is very simple and has no side effects at all so I don't see any reason to mock or stub this. It's too much cost for absolutely no profit. Not saying we shouldn't inject it though, but that depends on usage.– Steve Chamaillard
7 hours ago
@ArseniMourzenko so when injecting a calculator class implementing a
multiply
method, you'd mock this? Which means in order to refactor (and use the * operator instead), you'll have to change every single mock declaration in your code? Doesn't look like easy code to me. All I'm saying is toHex
is very simple and has no side effects at all so I don't see any reason to mock or stub this. It's too much cost for absolutely no profit. Not saying we shouldn't inject it though, but that depends on usage.– Steve Chamaillard
7 hours ago
1
1
@steve surely this is exactly what arseni is saying. The static call is bad design, you want your unit tests to test specific parts of the code and static prevents this. Saying 'its a simple function that will never break' doesnt help you when it does break
– Ewan
7 hours ago
@steve surely this is exactly what arseni is saying. The static call is bad design, you want your unit tests to test specific parts of the code and static prevents this. Saying 'its a simple function that will never break' doesnt help you when it does break
– Ewan
7 hours ago
1
1
@ArseniMourzenko I wasn't clear, I don't think having an interface is complex at all in this situation. I was saying that using mocks in these situations seem overkill and make tests harder to read, to write and to modify. When I say "doesn't look like easy code", I'm extrapolating to the case where
toHex
is used everywhere and so if tested with mocking every time well for any change I'll have to change many tests, right?– Steve Chamaillard
6 hours ago
@ArseniMourzenko I wasn't clear, I don't think having an interface is complex at all in this situation. I was saying that using mocks in these situations seem overkill and make tests harder to read, to write and to modify. When I say "doesn't look like easy code", I'm extrapolating to the case where
toHex
is used everywhere and so if tested with mocking every time well for any change I'll have to change many tests, right?– Steve Chamaillard
6 hours ago
|
show 9 more comments
Thanks for contributing an answer to Software Engineering Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f393870%2fhow-to-unit-test-methods-which-using-static-methods%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
Then all tests of Foo.Do will depend on the success of TestToHex_works
-- So? You don't have classes that depend on the success of other classes?– Robert Harvey♦
9 hours ago
2
I've never quite understood this obsession with free/static functions and their so-called non-testability. If a free function is free of side-effects, it is the easiest thing on the planet to test and prove it works. You've demonstrated this quite effectively in your own question. How do you test ordinary, side-effect free methods (that aren't dependent on class state) in object instances? I know you have some of those.
– Robert Harvey♦
9 hours ago
The only downside of this code using static functions is that you can’t easily use something else than
toHex
(or swap implementations). Apart from that everything is fine. Your code converting to hex is tested, now there’s another code using that tested code as a utility to achieve its own goal.– Steve Chamaillard
8 hours ago
2
I am completely missing what is the problem here. If ToHex doesn't work, then it's clear that Do won't work either.
– Simon B
8 hours ago
2
The test for Foo.Do() shouldn't know or care that it calls ToHex() under the covers, that's an implementation detail.
– 17 of 26
7 hours ago