Mocking Rust 🤪 and Testing 🧪

  Рет қаралды 37,168

Code to the Moon

Code to the Moon

Күн бұрын

A look at how to write integration and unit tests in Rust, including how to mock dependencies so that parts of the system can be tested in isolation.
00:00 Intro
00:53 Integration Tests
02:57 Unit Tests
04:17 Assert Macros
04:52 should_panic and ignored
05:43 cargo test
07:10 Mocking
11:52 Conclusion
---
Stuff I use to make these videos - I absolutely love all of these products. Using these links is an easy way to support the channel, thank you so much if you do so!!!
Camera: Canon EOS R5 amzn.to/3CCrxzl
Monitor: Dell U4914DW 49in amzn.to/3MJV1jx
Lens: Sigma 24mm f/1.4 DG HSM Art for Canon EF amzn.to/3hZ10mz
SSD for Video Editing: VectoTech Rapid 8TB amzn.to/3hXz9TM
Microphone: Rode NT1-A amzn.to/3vWM4gL
Microphone Interface: Focusrite Clarett+ 2Pre amzn.to/3J5dy7S
Tripod: JOBY GorillaPod 5K amzn.to/3JaPxMA
Keyboard: Redragon Mechanical Gaming Keyboard amzn.to/3I1A7ZD
Mouse: Razer DeathAdder amzn.to/3J9fYCf
Computer: 2021 Macbook Pro amzn.to/3J7FXtW
Caffeine: High Brew Cold Brew Coffee amzn.to/3hXyx0q
More Caffeine: Monster Energy Juice, Pipeline Punch amzn.to/3Czmfox
Building A Second Brain book: amzn.to/3cIShWf

Пікірлер: 78
@peter9477
@peter9477 Жыл бұрын
Love the nonchalant making of a function representing a "long-running calculation that results in the answer 42", with no further explanation than that. ;-)
@calvinlucian387
@calvinlucian387 Жыл бұрын
As a newbie to Rust and a strong supporter of TDD this is probably the best byte-sized intro to testing on KZfaq today imo. Thanks a lot!
@codetothemoon
@codetothemoon Жыл бұрын
Thanks calvinlucian, glad you found it valuable!
@calebdeming5515
@calebdeming5515 Жыл бұрын
This guy is awesome
@GeekMasher
@GeekMasher Жыл бұрын
Great video. One thing I might have added to this is Rusts documentation testing. This is an amazing feature of the language. You will know that the documentation you have written compiles and runs properly as tests in `cargo test`.
@codetothemoon
@codetothemoon Жыл бұрын
I actually haven't tried this, will check it out!
@ClearerThanMud
@ClearerThanMud 2 ай бұрын
Really like your Rust videos! Just wanted to say that I prefer to avoid mocking when possible by breaking a function into two parts: 1) a pure function that figures out what needs to be done and returns a description of that activity, and 2) an interpreter for that description. The interpreter will be straightforward and can often just be left for integration testing. All of the gnarly logic will be in the the pure function, which is now far easier to test: given these inputs, you should say that this needs to be done.
@0xccd
@0xccd Жыл бұрын
Perfect timing. I've been struggling with mocks in Rust. Thanks!
@codetothemoon
@codetothemoon Жыл бұрын
Glad this video could help! Mocking in Rust is definitely a bit tricky.
@r31527
@r31527 Жыл бұрын
You're awesome! I've been procrastinating reading the Rust testing docs & you taught me everything I need to get started :)
@codetothemoon
@codetothemoon Жыл бұрын
Fantastic, really happy it was helpful!
@Mustafa-099
@Mustafa-099 9 ай бұрын
This is Gold content on youtube!!! Loving every bit of it :)
@tosindaudu6595
@tosindaudu6595 Жыл бұрын
Please do refcell and cell next and soon. Thanks!
@codetothemoon
@codetothemoon Жыл бұрын
I've put it on the video idea list!
@mareknetzel
@mareknetzel Жыл бұрын
Your videos are perfect!
@codetothemoon
@codetothemoon Жыл бұрын
Thanks Marek, very happy you find them valuable!
@Marcos-tl2vy
@Marcos-tl2vy 6 ай бұрын
Thanks!!!!🎉🎉❤
@masiarek
@masiarek Жыл бұрын
Thank you!
@codetothemoon
@codetothemoon Жыл бұрын
You're welcome thanks for watching!
@mikerodent3164
@mikerodent3164 4 ай бұрын
Thanks, this was useful. The "mockall" crate seems to be added to "dependencies". But surely that crate shouldn't be included when you compile. If you add it to "dev-dependencies", however, you can't then include "[automock]" in the non-test code. How does this aspect work?
@zsoltpasztori8770
@zsoltpasztori8770 Жыл бұрын
Ignore can also be used if the integration test needs some hardware to pass. For example, the library is used to calculate average temperature, and you want to test it with an actual sensor.
@andythedishwasher1117
@andythedishwasher1117 Жыл бұрын
Super useful breakdown! This will be an essential skill set as I dive into this idea I recently had. I'm trying to determine the potential advantages, if any, of using Rust to indirectly write Javascript via some kind of translation macro for the purposes of maintaining memory safety in the resulting Javascript. This would be different from what frameworks like Yew are doing (which is definitely awesome) by bundling Rust logic into beautiful web assembly that works reluctantly alongside JS like an incompetent older brother who just happened to inherit the keys to the workshop. We wouldn't get the same kind of performance advantages, but we would still benefit from the memory safety checks quite a bit. I discovered that effect when I was very quickly able to rebuild my calculator app from Yew to Vue 3 with minimal debugging and a lot less code.
@codetothemoon
@codetothemoon Жыл бұрын
Thanks Andy! That would be an interesting undertaking. I wonder if the brevity of the Vue version is more due to the Vue framework than JavaScript itself. Not sure. Personally when I build with Yew I don't find myself missing JS or React, but I do find myself missing Svelte 🙃
@andythedishwasher1117
@andythedishwasher1117 Жыл бұрын
@@codetothemoon Svelte is the big one I plan to explore next before I land on a target framework. Working on a rebuild of my HQ domain with Vue to assess the resulting code base, then probably working on a rebuild and/or additional experiment in Svelte depending on how the Vue build goes. Lots of work ahead!
@davidraymond8994
@davidraymond8994 Жыл бұрын
Awesome Rust videos. I am a newbie to Rust and am learning a lot from you thanks so much. Do you have a course offering or anything like that?
@codetothemoon
@codetothemoon Жыл бұрын
Thanks David! I don't currently have a course offering (I'd love to have one though!) but I've seen many on Udemy and other online learning sites. Not sure which one is best, maybe ask in r/rust! Also Let's Get Rusty offers a course as well but I haven't tried it.
@mdshohidurrahman1121
@mdshohidurrahman1121 Жыл бұрын
Brain friendly,as always.
@codetothemoon
@codetothemoon Жыл бұрын
🧠 nice, brain friendliness is a big priority!
@irlshrek
@irlshrek Жыл бұрын
I use --nocapture to print stuff in the tests!
@flwi
@flwi Жыл бұрын
Thanks for this helpful video! This will take some time to get used to. I work mostly in scala and just started learning rust. Mixing code and tests in a single file just feels wrong to me so far.
@codetothemoon
@codetothemoon Жыл бұрын
Cool - I personally think Scala is a fantastic language - sometimes I wish there was some way to get Rust's performance with a more Scala-like syntax. And yeah, putting tests and code in the same file feels a little weird to me still. But I think there are advantages, like not needing to maintain a test file / directory structure that is essentially a duplicate of the one that already exists for your code.
@adicide9070
@adicide9070 6 ай бұрын
right so for somehting like this we'd definitely use a manual mock.
@oliverye5833
@oliverye5833 Жыл бұрын
If I use mockall, it requires mockall be a part of the dependency in the library. The example here wouldn't work if it's in the dev dependency. (Not sure if it's problem because I thought mock should be dev dependency as it's not related to actual context i.e api call)
@mikerodent3164
@mikerodent3164 4 ай бұрын
Puzzled Rust mocking newb here: I've just asked the same question one year later. Did you get an answer to this? i.e. how to not include that mockall crate when compiling?
@necauqua
@necauqua Жыл бұрын
There is one more interesting test binary flag, --nocapture. And in general, you didn't mention how the stdout is captured and printed only if the test fails - to keep successful test runs tidy
@codetothemoon
@codetothemoon Жыл бұрын
re: nocapture, I actually didn't know about this, thanks for pointing it out. and you're right, I should have mentioned that stdout is for successful tests.
@jhiver1978
@jhiver1978 Жыл бұрын
Another flag worthwhile mentioning IMHO would be cargo test -- --nocapture to occasionally output debug info
@codetothemoon
@codetothemoon Жыл бұрын
good point, probably should have included that!
@phenanrithe
@phenanrithe Жыл бұрын
More and more often I find that hosting the unit tests in the same file as the source code is distracting and inconvenient without real benefit, so I'm mostly keeping them in a tests-rs file which is technically the same. Just prepend the file with "#![cfg(test)]". It's easier to switch files than lines in the same file in the test/code design loop, and the tests-rs file is like a detailed spec/example for the whole crate / submodule (or tests_ if it becomes too big). Unless there aren't many tests of course.
@phenanrithe
@phenanrithe Жыл бұрын
(I have to write test-rs instead of test DOT rs otherwise silly KZfaq creates a link, which likely hides the comment as spam...)
@dealloc
@dealloc Жыл бұрын
I have never seen an example of changing a test file out being an actual use-case. Often because tests should be complete as a whole. Co-location makes it easier to find tests for the corresponding implementations imo. The only reason why I'd move unit tests to a separate file would be if the language didn't allow me to have it in the same place. If your tests become too big, that is also a good indication that your implementation likely does more than it needs. It makes it easier to discover where separation of concerns could be applied. But each to their own, as long as it's consistent I don't see any problem with either way of doing it.
@phenanrithe
@phenanrithe Жыл бұрын
@@dealloc I think it's a question of preference indeed, I just don't like to mix source code with test code. There's just no benefit, only inconvenience unless it's a very small file with very few tests.
7 ай бұрын
mockall should be in the devDependencies though right ?
@noblenetdk
@noblenetdk Жыл бұрын
How about the cargo plugin Nexttest? As alwas great explanation
@codetothemoon
@codetothemoon Жыл бұрын
Never heard of it, I've put it on the list of things to check out!
@kentheHar
@kentheHar Жыл бұрын
Do the mocks end up in the normal binary or only the test binary?
@codetothemoon
@codetothemoon Жыл бұрын
Good question I'm actually not 100% sure about this, but my hope is that they would be pruned out because they are not used. I'd be surprised if they weren't.
@samhanna7382
@samhanna7382 Жыл бұрын
is that the default vs code dark theme ?
@codetothemoon
@codetothemoon Жыл бұрын
Yep I believe it's called Dark+!
@mikechickenman
@mikechickenman Жыл бұрын
Don’t forget `cargo test - -nocapture`
@NexusGamingRadical
@NexusGamingRadical Жыл бұрын
So its impossible to mock structs without changes your code or the dependacy? :(
@enokoner
@enokoner 3 ай бұрын
good luck using mockall for nontrivial cases
@spoq9637
@spoq9637 Жыл бұрын
Hi, I’m qa automation. can i use rust for api tests? Thx!
@codetothemoon
@codetothemoon Жыл бұрын
I don't think there's anything preventing you from doing this! Whether it's the best choice for such a task, I'm not sure.
@dr.maninderjitkaur7805
@dr.maninderjitkaur7805 Жыл бұрын
I am too sober for tNice tutorials, I'll be back later..
@codetothemoon
@codetothemoon Жыл бұрын
🔥
@mufty9006
@mufty9006 Жыл бұрын
I always have to change my playback speed back to Normal. Can't afford to miss a word
@codetothemoon
@codetothemoon Жыл бұрын
Nice, I try to avoid any fluff!
@theroboman727
@theroboman727 Жыл бұрын
There is a browser extension I use called enhancer for youtube, where one of the features is the ability to change playback speed in 0.1x increments (can be configured) using ctrl+scroll wheel. Thought id mention this if you dont have anything similar already.
@SArthur221
@SArthur221 Жыл бұрын
11:12 you said we were going to test the get_answer() function, but what seems to have happened is the exact opposite: that BigComputer's implementation gets called the way we prescribe...
@jordanwhittle8713
@jordanwhittle8713 Жыл бұрын
I could be wrong but I think the idea behind the ‘times’ part is to specify the way that get_answer USES BigComputer Imagine if BigComputer was actually a database and compute_answer created a record in the database. With times(1), you would be able to specify that get_answer only calls compute_answer once to create 1 record in the database instead of calling compute_answer 1000 times and creating 1000 records. You’re not testing the mocked object, just specifying how it must be used.
@SArthur221
@SArthur221 Жыл бұрын
@@jordanwhittle8713 good point
@someon3
@someon3 Жыл бұрын
What are the real benefits of doing mock than construct the object directly?
@codetothemoon
@codetothemoon Жыл бұрын
Because constructing the object directly would make the test dependent on the behavior of that object - in unit tests we want to test a specific component in isolation, ideally without being affected by that component's dependencies and transitive dependencies. This is a bit easier to see when the component being tested has 10s or 100s of transitive dependencies.
@harleyspeedthrust4013
@harleyspeedthrust4013 Жыл бұрын
@@codetothemoon But if the thing being tested can't be isolated in real code because it depends on the thing we're mocking, then how do we expect to be able to test it in isolation? Doesn't that defeat the point of tests - to ensure that our code works when it runs in production?
@TehKarmalizer
@TehKarmalizer Жыл бұрын
@@harleyspeedthrust4013 that’s the argument. That when you test mocks, all you test is your ability to produce mocks. There are other types of testing, though. Unit testing is intended to test low level behavior.
@aazzrwadrf
@aazzrwadrf Жыл бұрын
what about logging?
@codetothemoon
@codetothemoon 11 ай бұрын
specifically in a testing context or in general?
@awnion
@awnion Жыл бұрын
That's all great until you actually need something like async_trait + trait inheritance 🤣
@JosephDalrymple
@JosephDalrymple Жыл бұрын
It's all fun and games until you try and reference a trait in your struct so that you can mock it's _async methods_. EDIT emphasized. Should've been more specific in the beginning. 😅
@dealloc
@dealloc Жыл бұрын
This is the same as get_answer, but `impl` abstracts away what is really going on. The expanded version of using `impl` is this: ``` fn get_answer(computer: &C, question: i32) -> String where C: BigComputer { // ... } ``` With structs it would be the same format: ``` struct GetAnswerMachine where C: BigComputer { computer: C; } ``` You can also use the short-hand syntax: ``` struct GetAnswerMachine { computer: C; } ``` This is called dependency injection, because it allows you to switch out what "C" is, as long as it implements the "BigComputer" trait. If GetAnswer does not use the entire BigComputer, you can split up the BigComputer trait into smaller traits and compose them where needed. Smaller traits are easier to deal with and decreases the surface area, avoiding breaking changes that could affect all implementations that rely on large traits.
@JosephDalrymple
@JosephDalrymple Жыл бұрын
@@dealloc Unless your struct uses async methods 😅
@jeffg4686
@jeffg4686 Жыл бұрын
Mocking Rust is the only way to get through learning it. I have full contempt by now, believe me. Question regarding asserts outside of tests - just in main code - would you always use debug_assert there. I'm still trying to figure out best practices in rust. My thought is that assert! in regular code is likely a bad idea (since it panics instead of allowing you a change to deal with an error result), but that debug_assert!() is useful since it's only in debug mode, but then that's kinda cheating your way out of having real error handling. So maybe even debug_assert isn't that useful in regular code. Maybe just as a placeholder to say "write some error handling here later"
@dealloc
@dealloc Жыл бұрын
Panicing is perfectly fine, mostly for internal implementations rather than user-facing APIs. It's better to panic and crash a program than ending up in a bad state that is unrecoverable and hard to debug. Assertions are not a replacement of error handling, but rather a compliment to it, by restricting the surface area of an implementation to avoid leaking internal details throughout the entire library/application, especially to user-facing APIs. Panics should be treated as bugs in the implementation. Rather than being a way to validate user input, it should be a way to validate input passed by the internal system. While you could pass Results everywhere in place of assertions but it makes it harder to avoid breaking changes in the code base and often easily leaks into user-land, where there is no way for the user to recover. Note that "user" in this case can be a user of a library, or a service interfacing with other services or programs.
@fleeb
@fleeb Жыл бұрын
Ooooh... by 'Mocking Rust', you mean using mocks to imitate real objects. I thought this video was going to make fun of the language.
@codetothemoon
@codetothemoon Жыл бұрын
yeah, it was a somewhat lame play on words 🙃
@hiongun
@hiongun Жыл бұрын
Why everything becomes dead complicated when it comes to Rust? Boy, it's just testing. Do you really think this is 'simple' ?
@codetothemoon
@codetothemoon Жыл бұрын
I don't think everything is complicated when it comes to Rust. But I think what you need to do to get mocking working is pretty awful. My gut feeling is that this complexity is due to the lack of support for inheritance, but I'm not 100% sure. In any case I hope the necessary language features get implemented that allow mocking to be a bit more concise.
Rust Powered Database SurrealDB (It's Pretty Ambitious)
11:28
Code to the Moon
Рет қаралды 107 М.
Rust Interior Mutability - Sneaking By The Borrow Checker
16:02
Code to the Moon
Рет қаралды 64 М.
OMG😳 #tiktok #shorts #potapova_blog
00:58
Potapova_blog
Рет қаралды 3,5 МЛН
World’s Deadliest Obstacle Course!
28:25
MrBeast
Рет қаралды 122 МЛН
A pack of chips with a surprise 🤣😍❤️ #demariki
00:14
Demariki
Рет қаралды 51 МЛН
Testcontainers have forever changed the way I write tests
12:11
Dreams of Code
Рет қаралды 110 М.
rust macros are magic
14:02
Tantan
Рет қаралды 44 М.
Stop Writing So Many Tests
10:02
Web Dev Simplified
Рет қаралды 81 М.
Rust Tests Itself (kind of!)
11:41
No Boilerplate
Рет қаралды 76 М.
8 deadly mistakes beginner Rust developers make
14:14
Let's Get Rusty
Рет қаралды 157 М.
Rust's Most Important Containers 📦 10 Useful Patterns
17:11
Code to the Moon
Рет қаралды 114 М.
Constructors Are Broken
18:16
Logan Smith
Рет қаралды 101 М.
Ace Rust Macros ♠️ the declarative kind
14:06
Code to the Moon
Рет қаралды 37 М.
The Uiua Programming Language Caught Me By Surprise
12:24
Code to the Moon
Рет қаралды 49 М.
creating your own errors in rust may be easier than you think
10:59
Brooks Builds
Рет қаралды 1,8 М.
How charged your battery?
0:14
V.A. show / Магика
Рет қаралды 7 МЛН
How To Unlock Your iphone With Your Voice
0:34
요루퐁 yorupong
Рет қаралды 26 МЛН
#miniphone
0:16
Miniphone
Рет қаралды 3,5 МЛН