Java AnyString() 作为单元测试的参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39418491/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AnyString() as parameter for unit test
提问by Sorona
I have to deal with a legacy application that has no tests. So before I begin refactoring I want to make sure everything works as it is.
我必须处理没有测试的遗留应用程序。所以在我开始重构之前,我想确保一切正常。
Now imagine the following situation:
现在想象以下情况:
public SomeObject doSomething(final OtherObject x, final String something) {
if(x == null) throw new RuntimeException("x may not be null!");
...
}
Now I want to test that null check, so to be sure it works and I don't lose it once I refactor.
现在我想测试该空检查,以确保它有效并且在重构后不会丢失它。
So I did this
所以我做了这个
@Test(expected = RuntimeException.class)
public void ifOtherObjectIsNullExpectRuntimeException() {
myTestObject.doSomething(null, "testString");
}
Now, this works of course.
现在,这当然有效。
But instead of "testString" I'd like to pass in a random String.
但是我想传入一个随机字符串而不是“testString”。
So I tried with:
所以我尝试了:
@Test(expected = RuntimeException.class)
public void ifOtherObjectIsNullExpectRuntimeException() {
myTestObject.doSomething(null, Mockito.anyString());
}
But this is not allowed., as I get
但这是不允许的。,正如我所知道的
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: ... You cannot use argument matchers outside of verifications or stubbing
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: ... 您不能在验证或存根之外使用参数匹配器
I do understand the meaning of this, but I wonder whether I can still manage to do what I want without parameterizing my test or the like. The only libraries I may use are Junit, AssertJ, Mockito and Powermock.
我确实理解这的含义,但我想知道我是否仍然可以在不参数化测试等的情况下做我想做的事情。我可能使用的唯一库是 Junit、AssertJ、Mockito 和 Powermock。
Any ideas?
有任何想法吗?
采纳答案by nasukkin
Well, like Mockito is trying to tell you via that exception, that's not really how you'd use anyString
. Such methods are only to be used by mocks.
好吧,就像 Mockito 试图通过该异常告诉您一样,这并不是您真正会使用的anyString
. 此类方法仅供模拟使用。
So, why not try testing with an actual random string? My personal favorite in such a scenario: java.util.UUID.randomUUID()
.toString()
. This will virtually always generate a brand new string that has never been used for your test before.
那么,为什么不尝试使用实际的随机字符串进行测试呢?在这种情况下,我个人最喜欢的是:. 这几乎总是会生成一个全新的字符串,该字符串以前从未用于您的测试。java.util.UUID.randomUUID()
.toString()
I'd also like to add that if you are writing tests for your SomeObject
class that you should avoid mocking SomeObject
's behavior. From your example, you weren't exactly doing that, but it looked like you might be going down that route. Mock the dependencies of the implementation you're trying to test, not the implementation itself! This is very important; otherwise you aren't actually testing anything.
我还想补充一点,如果你正在为你的SomeObject
类编写测试,你应该避免 mockingSomeObject
的行为。从你的例子来看,你并没有完全这样做,但看起来你可能会沿着这条路走下去。模拟您要测试的实现的依赖项,而不是实现本身!这是非常重要的; 否则你实际上并没有测试任何东西。
回答by Jashan Preet
Well i do not have much knowledge of mockito but you can always create your own random string generator. maybe that can work and u can modify more types of inputs in it
好吧,我对 mockito 了解不多,但您始终可以创建自己的随机字符串生成器。也许这可以工作,你可以修改更多类型的输入
回答by Code-Apprentice
Tests should be deterministic. Using random values in a test makes it difficult to reproduce behavior when debuging a failed test. I suggest that you just create a String
constant for the test such as "abcdefg"
.
测试应该是确定性的。在测试中使用随机值使得在调试失败的测试时难以重现行为。我建议您只String
为测试创建一个常量,例如"abcdefg"
.
回答by GhostCat
You are mixing up concepts here.
你在这里混淆了概念。
All those "mocking" helpers like anyString()are meant to be used when configuring a mockobject.
所有像anyString()这样的“模拟”助手都是在配置模拟对象时使用的。
But when you check your testing code:
但是当你检查你的测试代码时:
@Test(expected = RuntimeException.class)
public void ifOtherObjectIsNullExpectRuntimeException() {
myTestObject.doSomething(null, "testString");
}
you will find: there is absolutely no mocking involved for this test. You simply can'tuse those Mockito calls in that place; because "there is no Mockito" in that place.
您会发现:此测试绝对不涉及模拟。你根本不能在那个地方使用那些 Mockito 调用;因为那个地方“没有 Mockito”。
And just for the record - no need to go overboard here anyway. Your logic is very clear here: when the first argument is null, then you throw that exception. Thus it really doesn't matter at all what comes in as second argument. So thinking for an hour how to test null with any second argument is, well, in my eyes: waste of your time.
只是为了记录 - 无论如何都不需要在这里过火。您的逻辑在这里非常清楚:当第一个参数为空时,您将抛出该异常。因此,作为第二个参数出现的内容根本无关紧要。因此,思考一个小时如何使用任何第二个参数测试 null 是,好吧,在我看来:浪费您的时间。
Final hint: there is java.lang.ObjectsAnd that class has a nice check for null, so my production code only looks like
最后提示:有java.lang.Objects并且该类对 null 进行了很好的检查,所以我的生产代码看起来像
public SomeObject doSomething(final OtherObject x, final String something) {
Objects.requireNonNull(otherObject, "otherObject must not be null");
Objects.requireNonNull(something, "something must not be null");
Only difference there: requires... throws NullPointerExceptions
唯一的区别是:需要...抛出 NullPointerExceptions
Final finally: some people suggest to put final on every parameter; but I wouldn't do that. It adds novalue in 99% of all cases. It just means that you have more code to read; for no good reasons. But that is a question of style.
Final finally:有人建议在每个参数上都加上final;但我不会那样做。在 99% 的情况下,它没有增加任何价值。这只是意味着你有更多的代码要阅读;没有充分的理由。但这是一个风格问题。
EDIT on the comment about having a test to check for potential future changes: you shouldn't do that:
编辑关于进行测试以检查未来潜在变化的评论:你不应该这样做:
- To a certain degree, how your input is verified is an implementation detail. You don't test for implementation details. In other words:
- Your method has a certain contract (that you, for example specify informally by writing a javadoc that says "throws NPE on null input"). Your tests should verify exactlythat current contract. And the contract is: throws if first argument is null.
- 在某种程度上,如何验证您的输入是一个实现细节。您不测试实现细节。换句话说:
- 你的方法有一个特定的契约(例如,你通过编写一个写着“在空输入上抛出 NPE”的 javadoc 来非正式地指定)。您的测试应准确验证当前合同。合同是:如果第一个参数为空则抛出。
And maybe another point of view; as I still think you are wasting your time here! You should make sure that all your interfaces are clear, easy to understand, and easy to use. That they allow users of your code to do the right thing easily; and prevent him from doing wrong things. That is what you should focus on - the quality of your interfaces as a whole! So instead of worrying how you could write a test for potential future changes; just make sure that your code base is overall consistent.
也许是另一种观点;因为我仍然认为你在这里浪费时间!您应该确保所有界面都清晰、易于理解且易于使用。它们允许您的代码的用户轻松地做正确的事情;并防止他做错事。这就是您应该关注的 - 整个界面的质量!因此,与其担心如何为未来的潜在变化编写测试;只需确保您的代码库整体一致即可。