Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@ioleo
Copy link
Member

@ioleo ioleo commented Mar 31, 2020

Fixes #2734

This PR introduces support for ZStream/ZSink and non-ZIO methods (regular functions/vals) as well as many refactorings/renames as the additional use cases crystalized the design to be more clean.

To be completed it still needs:

  • add support for ZStream/ZSink and non-ZIO methods in @mockable macro
  • add support for ZStream/ZSink and non-ZIO methods in @accessible macro
  • add test coverage for more advanced use cases composing Streams with Effects
  • add more advanced examples of mocks composing Streams with Effects

@adamgfraser @jdegoes Once these are completed I'd say ZIO Mock is 1.0 ready. I'll try to complete these as soon as possible. Opening the PR earlier so you can track progress and review the approach.

Out of the scope of this PR is support for polymorphic ZStreams/ZSinks. It will be tricky to get right, so I'll tackle it seperately and would not like it to be a blocker for this PR.

@ioleo
Copy link
Member Author

ioleo commented Apr 2, 2020

Updated @mockable macro.

@ioleo
Copy link
Member Author

ioleo commented Apr 2, 2020

As soon as CI finishes this is ready to be reviewed & merged @adamgfraser .

@ioleo
Copy link
Member Author

ioleo commented Apr 3, 2020

@adamgfraser can we rerun https://app.circleci.com/pipelines/github/zio/zio/6519/workflows/3cf22b04-08a3-4c31-9752-bb78704e3270/jobs/67033 ?
it works locally, I suspect this is some flaky test

Copy link
Contributor

@adamgfraser adamgfraser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of questions and comments but ready to go whenever you are.

## Creating a mock service

We'll be assuming you've read [How to use modules and layers][doc-use-modules-and-layers] guide. In the main sources we define the _service_, a module alias and _capability accessors_. In test sources we're defining the _mock object_ which will hold _capability tags_ and mock layer machinery.
We'll be assuming you've read [How to use modules and layers][doc-use-modules-and-layers] guide. In the main sources we define the _service_, a module alias and _capability accessors_. In test sources we're defining the _mock object_ which extends `zio.test.mock.Mock` which holds _capability tags_ and _compose layer_.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great that we have a clear separation between source and test now!

def overloaded(arg1: Long) = invoke(Overloaded._1, arg1)
val compose: URLayer[Has[Proxy], Example] =
ZLayer.fromServiceM { proxy =>
withRuntime.map { rts =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe say something about what this is so people don't just think they can do ZIO.runtime[R]?

def overloaded(arg1: Int) = proxy(Overloaded._0, arg1)
def overloaded(arg1: Long) = proxy(Overloaded._1, arg1)
def function(arg1: Int) = rts.unsafeRunTask(proxy(Function, arg1))
def sink(a: Int) = rts.unsafeRun(proxy(Sink, a).catchAll(error => UIO(ZSink.fail(error))))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to unsafely run a sink or a stream?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The internal mock machinery returns an IO[E, A] where A <: ZStream or A <: ZSink.
For ZStream E = Nothing, becouse any errors happening in creation of the stream are deferred to the first take (moved into streams error channel ZStream[_, E, _]). For ZSink any errors happening upon creation are caught immidietly resulting in a failed Sink, so we need to manually move the error from our internal mock IO[E, _] to a failed ZSink.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we do something like io.foldCauseM(e => ZStream.fail(e), stream)? Maybe I'm not understanding.

- `E` is the type of error it can fail with
- `A` is the type of return value it can produce

The `Capability` type is not publicly available, instead you have to extend `Mock` dependent types `Effect`, `Method`, `Sink` or `Stream`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any other types we want to support mocking? ZManaged? ZSTM? Any way to abstract over this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should have all ZIO data types covered. I don't see a clean way to abstract over this ATM, but will definately think about it in future.

*/
abstract class Method[R <: Has[_]: Tagged, I: Tagged, E: Tagged, A: Tagged](val compose: URLayer[Has[Proxy], R])
extends Method.Base[R] { self =>
protected[mock] abstract class Capability[R <: Has[_]: Tagged, I: Tagged, E: Tagged, A: Tagged](val mock: Mock[R])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add variance here or no because of the tags?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't. Variance will break things.

/**
* A `Mock[R]` represents a mockable environenment `R`.
*/
abstract class Mock[R <: Has[_]: Tagged] { self =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Covariant?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably break things, but have not tested. I don't think it would bring any value though, at least in current implementation.

@adamgfraser adamgfraser merged commit eb3501c into zio:master Apr 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ZIO Mock: support methods that accept streams and/or produce streams

2 participants